How to receive a JSON File with multiple nodes through a POST Request with JAX-RS and Jackson (Quarkus) - jackson

When im tryin got do a Post request through my JAX-RS API it always sends a null value. I dont know if the Jackson annotations are incorrect or if i need to use an ObjectMapper.
These are my classes:
public class ClassA{
private String name;
private ClassB classB;
public ClassA(){}
public ClassA(String name, ClassB classB){
this.name = name;
this.classB = classB;
}
#JsonGetter
public String getName(){ return name; }
#JsonGetter
public ClassB getClassB(){ return classB; }
and this is the classB
public class ClassB{
#JsonProperty("type")
private String type;
#JsonProperty("number")
private int number;
public ClassB(){}
#JsonPropertyOrder({"type, number"})
public ClassB(String type, int number){
this.type= type;
this.number= number;
}
#JsonGetter
public String getType(){ return type; }
#JsonGetter
public int getNumber(){ return number; }
My JSON file:
{
"type": "typeExample;
"classB": {
"type": "classBTypeExample";
"int": 10;
}
}
I want Jackson to read the file and then add an Object type ClassA to a list (the problem is that is not even reading it)
This is the API code:
#Path("/path")
public class Requests {
private Set<ClassA> classesA = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
#GET
public Set<ClassA> list() {
return classesA;
}
#POST
public Set<ClassA> add(ClassA classA){
classesA.add(classA);
return classesA;
}
}
I already added the quarkus.jackson.fail-on-unknown-properties=true to the application.properies file

It was a simple thing that i didnt notice. I forgot to set the values on the constructer. So i just had to add the #ConstructorProperties({}) to the classes constructors and it worked out.

Related

Jackson - Deserialize with JsonView

I am trying to restrict which properties from a JSON object are deserialised using Jackson JSONViews. The aim is to use this to prevent consumers of my API from submitting data that they shouldn't.
The problem is, I have either misunderstood JSONViews or I am doing something wrong. See below.
I started trying to do this in Spring but have noticed that even the simple test below doesn't work.
Account Class
public class Account {
#Id
private String id;
private String name;
private List<String> items;
private List<User> users;
#JsonView(AccountViews.Private.class)
public void setId(String id) {
this.id = id;
}
#JsonView(AccountViews.Public.class)
public void setName(String name) {
this.name = name;
}
#JsonView(AccountViews.Public.class)
public void setItems(List<String> items) {
this.items = items;
}
#JsonView(AccountViews.Private.class)
public void setUsers(List<User> users) {
this.users = users;
}
}
Views
public class AccountViews {
public interface Public {}
public interface Private extends Public {}
}
Test
#Test
public void testDeserialization(){
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
Account account = mapper.readerWithView(AccountViews.Public.class).forType(Account.class).readValue("{ \"name\": \"account1\", \"items\": [\"item1\"], \"users\": [ { \"firstname\": \"user1_firstname\", \"lastname\": \"user1_lastname\" }] }");
assertEquals(account.getName(), "account1");
assertNull(account.getUsers());
}
Unforunately, the 2nd assertion fails because Users has a user object inside.
Basically, even though "users" is a property of Account, I don't want the value to be deserialized because I have used the JSONView (AccountViews.Public.class). However, whatever I try it always seems to be deserialized and is present on the account object.
Any help much appreciated.
Error
`java.lang.AssertionError: expected null, but was:<[User#609db43b]>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotNull(Assert.java:755)
at org.junit.Assert.assertNull(Assert.java:737)
at org.junit.Assert.assertNull(Assert.java:747)
at`

Jackson deserialization issue with access modifier

Jackson throwing an exception in deserialization with protected access modifier.
I am trying to deserialize one object then accessing protected properties of parent class is throwing exception.
Class com.fasterxml.jackson.databind.deser.impl.FieldProperty can not
access a member "protected"
Make sure that Jackson can see protected fields. E.g.
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC;
#JsonAutoDetect(fieldVisibility = PROTECTED_AND_PUBLIC)
class Person {
protected String name;
}
Or define getters and setters as needed. E.g. :
class Person {
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

Dropwizard hiding field in json

What's the best way to hide a field on a model in Dropwizard? (If I want to be able to deserialize the field via Jackson, but hide it when serialization)
For example, if I have the following model:
class User {
private String secret;
private String username;
}
I want to be able to create a User with a secret via calling new ObjectMapper().readValue(), but I want to hide the secret field it when it's serialized into JSON.
Add #JsonIgnore annotation before the property
Or you can add #JsonIgnoreProperties annotation and specify the fields which are to be excluded
public class Foo{
#JsonIgnore
private String bar;
...
}
or
#JsonIgnoreProperties(value = { "bar" })
public class Foo {
private String bar;
...
}
or if you want to ignore this field only on serialization, and not on deserialization then
public class Foo{
private String bar;
...
#JsonIgnore
public String getBar(){
return bar;
}
public void setBar(String bar){
this.bar = bar;
}
}
If you want to hide it only during seriazliation add #JsonIgnore annotation to property getter.
class User {
#JsonProperty
private String secret;
#JsonProperty
private String username;
#JsonIgnore
public String getSecret(){
return secret;
}
public void setSecret(String secret){
this.secret = secret;
}
...
}

Overriding properties from abstract class in Salesforce Apex

I have an abstract class in apex with several properties that I would like to override in a child class. According to the documentation, properties support both the override and virtual access modifiers. However, when I try to use either of them in either the parent or child class, I get an error saying that variables cannot be marked as virtual/override. Here is a facsimile of the code that causes this error:
public abstract class Row{
public virtual double value{
get{return value==null ? 0 : value;}
set;
}
}
public class SummaryRow extends Row{
private list<Row> childRows;
public override double value{
get{
totalValue = 0;
for(Row childRow:childRows){
totalvalue += childRow.value;
}
return totalValue;
}
}
}
Is this functionality not supported, or is there something that I am missing?
Thanks in advance.
Unfortunately, as far as I know that is a mistake in the documentation. I've only been able to apply the override and virtual modifiers to methods. You can, of course, get the desired effect by manually writing your property getter/setter methods:
public abstract class TestRow {
public Double value;
public virtual Double getValue() {
return value==null ? 0 : value;
}
public void setValue(Double value) {
this.value = value;
}
}
public class SummaryTestRow extends TestRow {
private list<TestRow> childRows;
public override Double getValue() {
Double totalValue = 0;
for(TestRow childRow : childRows){
totalValue += childRow.value;
}
return totalValue;
}
}

Custom datacontract / datamember name

I have a following problem. A customer requested a web service that returns data in following format:
<status>
<name1>Some name</name1>
...
</status>
But when an error occurs they want to get a following message:
<status>
<error>Error description</error>
</status>
I created a web service using WCF and in order to fulfill the requirements I defined a following service contract:
[ServiceContract]
public interface IPatronStatus
{
[OperationContract]
[ServiceKnownType("GetKnownTypes", typeof(KnownTypesProvider))]
[WebGet(UriTemplate = "/service/status?user={unilogin}")]
StatusData GetPatronStatus(string unilogin);
}
And also defined a following base class:
[DataContract(Name="status")]
public class StatusData
{
}
And two derrived classes:
public class PatronStatusData : StatusData
{
private string _name;
[DataMember(Name = "name1", Order = 0)]
public string Name
{
get { return _name; }
set { _name = value; }
}
...
}
And:
public class UniLoginNotFoundError : StatusData
{
public UniLoginNotFoundError()
{ }
private string _description = "UniLoginNotFoundError";
[DataMember(Name = "error", Order = 0)]
public string Description
{
get
{
return _description;
}
}
}
The problem is that when I pull the data from the web service the data contract name ("status") and the names of the data members are ignored and the type's and properties' names are used.
Is it possible to use the custome names?
You should decorate both UniLoginNotFoundError and PatronStatusData with DataContract(Name="Something") to make this work. But you won't be allowed to set the same name ("status") for them.
In your particular case I'd better use single class with unused properties set to null.
[DataContract(Name="status")]
public class StatusData
{
private string _name;
private string _errorDescription = null;
[DataMember(Name = "name1", Order = 0, EmitDefaultValue=false)]
public string Name
{
get { return _name; }
set { _name = value; }
}
[DataMember(Name = "error", Order = 1, EmitDefaultValue=false)]
public string Description
{
get{ return _errorDescription ;}
set {_errorDescription =value ;}
}
...
}
Generally speaking, it's a mistake to want too much control over the XML generated by serializing a Data Contract. That's the trap of the XML Serializer. Define the contract in general terms, and have the clients just consume the result, which will generally be simple enough.