Jackson: What happens if the property is out?

What happens if I annotate the constructor parameter using @JsonProperty , but Json does not specify this property. What value does the constructor get?

How to distinguish a property that has a null value from a property that is not in JSON?

+47
java jackson
Nov 30 2018-11-11T00:
source share
5 answers

Summing up the excellent answers Programmer Bruce and StaxMan :

  • Missing properties referenced by the constructor are assigned default values as defined by Java .

  • You can use setter methods to distinguish between properties that are implicitly or explicitly set. Methods Setter is called only for properties with explicit values. Setter methods can track whether a property has been explicitly set using a Boolean flag (for example, isValueSet ).

+37
Jan 25 2018-12-21T00:
source share

What happens if you annotate a constructor parameter using @JsonProperty, but Json does not specify this property. What value does the constructor get?

For questions like this, I like to just write an example program and see what happens.

The following is an example program.

 import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.map.ObjectMapper; public class JacksonFoo { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // {"name":"Fred","id":42} String jsonInput1 = "{\"name\":\"Fred\",\"id\":42}"; Bar bar1 = mapper.readValue(jsonInput1, Bar.class); System.out.println(bar1); // output: // Bar: name=Fred, id=42 // {"name":"James"} String jsonInput2 = "{\"name\":\"James\"}"; Bar bar2 = mapper.readValue(jsonInput2, Bar.class); System.out.println(bar2); // output: // Bar: name=James, id=0 // {"id":7} String jsonInput3 = "{\"id\":7}"; Bar bar3 = mapper.readValue(jsonInput3, Bar.class); System.out.println(bar3); // output: // Bar: name=null, id=7 } } class Bar { private String name = "BLANK"; private int id = -1; Bar(@JsonProperty("name") String n, @JsonProperty("id") int i) { name = n; id = i; } @Override public String toString() { return String.format("Bar: name=%s, id=%d", name, id); } } 

As a result, the constructor is passed by default to the data type.

How to distinguish a property that has a null value from a property that is not in JSON?

One simple approach would be to check the default deserialization processing, because if the element was present in JSON but had a null value, then a null value would be used to replace any default value specified by the corresponding Java field, For example:

 import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; import org.codehaus.jackson.annotate.JsonMethod; import org.codehaus.jackson.map.ObjectMapper; public class JacksonFooToo { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY); // {"name":null,"id":99} String jsonInput1 = "{\"name\":null,\"id\":99}"; BarToo barToo1 = mapper.readValue(jsonInput1, BarToo.class); System.out.println(barToo1); // output: // BarToo: name=null, id=99 // {"id":99} String jsonInput2 = "{\"id\":99}"; BarToo barToo2 = mapper.readValue(jsonInput2, BarToo.class); System.out.println(barToo2); // output: // BarToo: name=BLANK, id=99 // Interrogate barToo1 and barToo2 for // the current value of the name field. // If it null, then it was null in the JSON. // If it BLANK, then it was missing in the JSON. } } class BarToo { String name = "BLANK"; int id = -1; @Override public String toString() { return String.format("BarToo: name=%s, id=%d", name, id); } } 

Another approach would be to implement a custom deserializer that checks for the required JSON elements. And another approach would be to write an extension request with Jackson's project at http://jira.codehaus.org/browse/JACKSON

+32
Nov 30 '11 at 4:16
source share

In addition to the constructor behavior explained in @Programmer_Bruce's answer, one way to distinguish between a null value and a missing value is to define a setter: setter is called only with an explicit null value. The custom setter can then set a private boolean flag ("isValueSet" or something else) if you want to track the set values.

Setters have priority over fields if both the field and the setter exist, so you can also "override" the behavior.

+10
Nov 30 '11 at 4:41
source share

I am thinking of using something in the style of the Option class, where the Nothing object will tell me if there is such a value or not. Has anyone done something similar with Jackson (in Java, not Scala, etc.)?

+2
Feb 10 '14 at 23:33
source share

(My answer may be useful for some people who find this thread via google, even if it does not answer the OP question)
If you are dealing with primitive types that are not available, and you do not want to use the installer, as described in other answers (for example, if you want your field to be final), you can use box objects:

 public class Foo { private final int number; public Foo(@JsonProperty Integer number) { if (number == null) { this.number = 42; // some default value } else { this.number = number; } } } 

this does not work if JSON really contains null , but this may be enough if you know that it will contain only primitives or be absent

0
May 18 '17 at 11:20
source share



All Articles