Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson deserialize default values missing

I try to deserialize a JSON object that I receive in my API using the following code:

ObjectMapper mapper = new ObjectMapper();
ExampleDto ed = mapper.readValue(req.body(), ExampleDto.class);

My class uses Lombok to generate constructors, getters and setters, and looks like this:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExampleDto {
    private String name = "";
    private List<String> values = new LinkedList<>();
}

Both properties should be optional, and use the default value specified in the class definition if they are not provided. However, if I now try to deserialize the JSON

{name: "Foo"}

the values field is null. From my understanding, and all example code I found, values should be an empty list.

Edit: Not a duplicate, as I'm using Lombok without Optionals

like image 548
user1839433 Avatar asked Feb 10 '18 21:02

user1839433


People also ask

How do I ignore Jsonproperty?

To ignore individual properties, use the [JsonIgnore] attribute. You can specify conditional exclusion by setting the [JsonIgnore] attribute's Condition property. The JsonIgnoreCondition enum provides the following options: Always - The property is always ignored.

Does Jackson require default constructor?

Need of Default ConstructorBy default, Java provides a default constructor(if there's no parameterized constructor) which is used by Jackson to parse the response into POJO or bean classes.

Does Jackson ObjectMapper use reflection?

Without any annotations, the Jackson ObjectMapper uses reflection to do the POJO mapping. Because of the reflection, it works on all fields regardless of the access modifier.

What is ObjectMapper class in Jackson?

ObjectMapper is the main actor class of Jackson library. ObjectMapper class ObjectMapper provides functionality for reading and writing JSON, either to and from basic POJOs (Plain Old Java Objects), or to and from a general-purpose JSON Tree Model (JsonNode), as well as related functionality for performing conversions.


1 Answers

@AllArgsConstructor creates the following constructor

@ConstructorProperties({"name", "values"})
ExampleDto(String name, List<String> values) {
    this.name = name;
    this.values = values;
}

The constructor is annotated with @ConstructorProperties which means a property-based creator (argument-taking constructor or factory method) is available to instantiate values from JSON object so jackson-databind uses this constructor to instantiate an object from ExampleDto class.

When the following line executes

mapper.readValue("{\"name\": \"Foo\"}", ExampleDto.class);

because there's no value for values in the provided JSON, null is passed for the second argument when the constructor is invoked.

If you remove @AllArgsConstructor annotation jackson-databind would use setter methods to initialize the object and in this case values would not be null

like image 85
Mohammad Alavi Avatar answered Oct 01 '22 00:10

Mohammad Alavi