85

In the example

class Person {
   String name;
   int age;
}

If the JSON object has a missing property 'age',

{
    "name": "John"
}
Person person = objectMapper.readValue(jsonFileReader, Person.class);

it throws a JsonMappingException saying it cannot deserialize. Is there an annotation to ignore missing fields during deserialization?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
user379151
  • 1,289
  • 1
  • 16
  • 25

7 Answers7

115

@JsonIgnoreProperties(ignoreUnknown = true) on the class level worked for me.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Gustavo Matias
  • 3,508
  • 3
  • 27
  • 30
  • 3
    This is working but at a higher level. Take care because it prevent the system to trigger an exception in case of "mismatching" json parameter. – Tobliug Oct 19 '16 at 07:45
  • 48
    This is not answer for the question. `JsonIgnoreProperties(ignoreUnknown = true)` is only useful when the incoming JSON message contains more properties than the object you try to serialize into. – Tamas G. Dec 19 '19 at 11:21
  • 3
    @TamasG.that may be the intention of this annotation, but it can't be denied it actually does work to solve the issue (at least as of Jackson 2.1.1). – cgull Mar 23 '21 at 21:42
58

I think what you want is

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Person {
  ...
}

that's the Jackson 1.x way. I think there's a new way in 2.x. Something like

@JsonInclude(Include.NON_NULL)
public class Person {
  ...
}

These will tell Jackson to only serialize values that are not null, and don't complain when deserializing a missing value. I think it will just set it to the Java default.

pedorro
  • 3,079
  • 1
  • 24
  • 24
43

Annotation-based approach is a better way for ignoring, but if needed, the manual way of deserialization is:

ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Person       person = mapper.readValue(jsonFileReader, Person.class);
Pang
  • 9,564
  • 146
  • 81
  • 122
Fırat Küçük
  • 5,613
  • 2
  • 50
  • 53
  • 1
    Do you mind explaining _why_ annotation based approach is better than "manual way"? – jayeffkay May 22 '17 at 09:39
  • 3
    @jayeffkay In general just focusing on Pojo instead of deserialization logic is preferred way. You can consider it like creating a JDBC connection manually vs ORM Entities. But If you want a custom solution. The manual way is welcome. – Fırat Küçük May 23 '17 at 15:55
  • 2
    I think the manual way is useful when the legacy code cannot be changed. For example, implementing E2E tests, where serialization/deserialization is a major part of working with objects, but the code itself cannot be changed. – sna19 May 28 '18 at 12:27
  • 4
    Whether using annotations or logic is better is dependent upon the situation. By putting the annotation on the pojo it ties the pojo to the underlying serialization mechanism, which in some cases is not desirable. Note that the name "plain old Java object" itself implies that the object is a "plain" object, not an object that is tied to particular technology (other than Java, of course!) – bartonstanley Sep 24 '18 at 19:04
19

Modern versions (2.9.6) of Jackson libraries will ignore missing creator properties by default. However, if the ObjectMapper configuration is set to:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, true);

Then you'll get a deserialization error if one of the properties is missing.

Moisés
  • 491
  • 4
  • 12
  • 2
    This is the answer that solved it for me. Jackson's default behavior of **deserializing missing primitive properties as 0/false** is just crazy, it should be opt-in and not opt-out. I ran across this when trying to deserialize JSON numbers to Kotlin data classes (with constructor properties), and only found https://stackoverflow.com/questions/14434679 first. – TheOperator Jan 03 '19 at 09:36
  • 1
    Looking at the Javadoc of `DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES`, this seems to be the behaviour since Jackson 2.6, i.e. since July 2015. – malamut Jun 15 '21 at 14:26
7

In Deserialization, two things may happen.

we have a new field in JSON String, not in Java Bean, that will be an unknown property for the object mapper. To ignore the unknown property, the object mapper configuration needs to be configured as below

ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

If a field is not in JSON String but in Java Bean, then that field will be treated as a missing property by the object mapper. To not fail on missing property, the object mapper configuration needs to be configured as below but this is the default behavior of Modern versions (2.9.6) of Jackson libraries.

ObjectMapper().configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, false)

Sivaram Rasathurai
  • 5,533
  • 3
  • 22
  • 45
  • Should this work when deserializing XML? No luck for me. – WillHaslett Nov 02 '22 at 17:45
  • Hi WillHaslett, can you check on this blog https://www.baeldung.com/jackson-xml-serialization-and-deserialization – Sivaram Rasathurai Nov 03 '22 at 02:38
  • I've spent a bunch of time with various docs and vanilla deserialization works fine. Jackson's support for XML that it didn't create is, I've come to learn, iffy. Setting FAIL_ON_MISSING_CREATOR_PROPORTIES or not on my mapper object has no impact on whether or not Jackson fails deserialization, complaining about a "required" property that is missing. – WillHaslett Nov 04 '22 at 17:21
  • There's nothing complicated about what I'm parsing. Here, if `SSTPID` is present, everything works. If I simply remove it from the XML, no dice. Same for any other element that is represented in the POJO class. KY000000159867000001 S00151801 SERWithPayment A A – WillHaslett Nov 04 '22 at 17:27
  • There is compilation error, ObjectMapper().configure is only applicable to SerializationConfig.Feature – Mubasher Dec 12 '22 at 09:35
3

You could also change your class to use an Integer instead of an int, in which case Jackson will handle null/missing "age" values properly. Just adding this answer for those looking for an alternative that doesn't involve using annotations.

class Person {
   String name;
   Integer age;
}
mbonness
  • 1,612
  • 1
  • 18
  • 20
1

if you annotate age with @JsonProperty(access = JsonProperty.Access.READ_ONLY) it will be ignored during deserialization only.

abdel
  • 643
  • 1
  • 5
  • 13