DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • JSON-Based Serialized LOB Pattern
  • How To Check for JSON Insecure Deserialization (JID) Attacks With Java
  • What Is Ant, Really?
  • Apache Spark 3 to Apache Spark 4 Migration: What Breaks, What Improves, What's Mandatory

Trending

  • AWS Kiro: The Agentic IDE That Makes Specs the Unit of Work
  • We Went Multi-Cloud and Almost Drowned: Lessons From Running Across AWS, GCP, and Azure
  • The Death of "Text-Only" ChatOps: Why Google's A2UI Matters for DevOps and SRE
  • How AI Coding Assistants Are Changing Developer Flow
  1. DZone
  2. Coding
  3. Languages
  4. Jackson, JSON and the Proper Handling of Unknown Fields in APIs

Jackson, JSON and the Proper Handling of Unknown Fields in APIs

How to proper deserialize json to java objects without facing UnrecognizedPropertyException when getting unkown fields or properties when consuming rest API.

By 
Gilvan Filho user avatar
Gilvan Filho
·
Jul. 09, 20 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
27.0K Views

Join the DZone community and get the full member experience.

Join For Free

Imagine the following scenario: You have an application that integrates with another through the consumption of REST endpoints. To perform serialization/deserialization you use the famous Jackson library that magically transforms java objects into JSON (serialization) and vice versa (deserialization). One fine day, quite suddenly, your requests stop working with an exception similar to the one below:

Plain Text
 




x


 
1
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field


What could have happened? The exception itself tells you: There are unknown attributes in JSON that deserialization is being performed.


Explaining the Exception

According to the official documentation:

Specialized JsonMappingException sub-class specifically used to indicate problems due to encountering a JSON property that could not be mapped to an Object property (via getter, constructor argument or field).

Succinctly whenever there is a property in the JSON that has not been mapped to its java / DTO object, Jackson will throw this exception.


So What Could Have Happened?

The service provider your application is consuming has added a new attribute in the return of the service. Since such an attribute does not exist in your java / DTO object, we have an unrecognized property, making the deserialization process impossible (JSON -> object).


Ok, Sherlock! And now?

To paraphrase, and correct myself: whenever there is a property in JSON that has not been mapped to its java / DTO object, Jackson will throw this exception, *unless you tell Jackson that he can ignore such attributes*.

Ignoring Unknown Fields with Jackson

Fortunately, there are two ways to work around the problem in question and avoid throwing the exception: 

  1. Annotate the class with @JsonIgnoreProperties (ignoreUnknown = true)
  2. Set the Deserialization Feature FAIL_ON_UNKNOWN_PROPERTIES to false


@JsonIgnoreProperties(ignoreUnknown=true)

Adding to your class @JsonIgnoreProperties(ignoreUnknown = true) annotation will tell Jackson to ignore unknown attributes when deserializing JSONs to objects in that class.

Java
 




xxxxxxxxxx
1
11
9


 
1
@JsonIgnoreProperties(ignoreUnknown=true)
2
public class AnnotatedPersonDto {
3
  private String name;
4
  private String sex;
5
  // ...
6
}



Set the Deserialization Feature FAIL_ON_UNKNOWN_PROPERTIES to false

Setting up the object mapper will tell Jackson to ignore unknown attributes in all deserializations where that object mapper is used.

Java
 




xxxxxxxxxx
1


 
1
// version 1.9 or before
2
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
3

          
4
// version 2.0 or after
5
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);



Let's Go to Tests

For our tests, we will need two DTO’s, one without an annotation (to prove the exception was thrown) and another with an annotation (to prove the resolution of the problem).

Java
 




x


 
1
public class UnannotatedPersonDto {
2
  private String name;
3
  private String sex;
4
  // ...
5
}
6

          
7
@JsonIgnoreProperties(ignoreUnknown=true)
8
public class AnnotatedPersonDto {
9
  private String name;
10
  private String sex;
11
  // ...
12
}


The JSON below will be used, which has the age attribute that is not known by the DTO.

JSON
 




xxxxxxxxxx
1


 
1
{ "name": "LINUS" , "age": 18, "sex": "MALE" }


Below we have 3 tests:

Java
 




xxxxxxxxxx
1
49


 
1
@SpringBootTest
2
class JacksonIgnorePropertiesTests {
3

          
4
  private String JSON_TO_DESERIALIZE = "{ \"name\": \"LINUS\" , \"age\": 18, \"sex\": \"MALE\" }";
5
    
6
    @Test
7
    void withJsonWithUnknownAttributes_whenWithoutAnnotationOrConfiguration_thenThrownException() throws JsonMappingException, JsonProcessingException {
8
      ObjectMapper mapper = new ObjectMapper();
9
      assertThrows(UnrecognizedPropertyException.class, () -> { mapper.readValue(JSON_TO_DESERIALIZE, UnannotatedPersonDto.class); });
10
    }
11
 
12
    @Test
13
    void withJsonWithUnknownAttributes_whenDtoHasAnnotationJsonIgnoreProperties_thenWillDeserialize() throws JsonMappingException, JsonProcessingException {
14
      ObjectMapper mapper = new ObjectMapper();
15
      assertEquals("LINUS", mapper.readValue(JSON_TO_DESERIALIZE, AnnotatedPersonDto.class).getNome());
16
    }
17

          
18
    @Test
19
    void withJsonWithUnknownAttributes_whenObjectMapperIsConfigured_thenWillDeserialize() throws JsonMappingException, JsonProcessingException {
20
      ObjectMapper mapper = new ObjectMapper();
21
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
22
      assertEquals("LINUS", mapper.readValue(JSON_TO_DESERIALIZE, UnannotatedPersonDto.class).getNome());
23
    }
24

          
25
}



Results:

The exception UnrecognizedPropertyException is thrown once JSON is deserialized using the class without annotation and no configuration has been added to the Object Mapper;

Deserialization is successful since the DTO that has the annotation used to ignore unknown attributes;

Deserialization also occurs successfully because despite using the DTO without the annotation to ignore unknown attributes, the object mapper was configured with the FAIL_ON_UNKNOWN_PROPERTIES feature that ignores those attributes.


Conclusion

So what is the best approach? It depends.

The approach of annotating classes with @JsonIgnoreProperties allows for finer control over which objects should ignore unknown fields and which should not. On the other hand, a developer may forget to put the annotation to a class, and then the problem could occur.

The approach of configuring the object mapper in line with a dependency injection framework, ensuring that the same object mapper is used throughout the whole system, will guarantee the extinction of the exception throughout the application, but leaving the developers blindfolded in relation the evolves that occur in API being consumed.

JSON Jackson (API) Object (computer science) Attribute (computing) Java (programming language)

Published at DZone with permission of Gilvan Filho. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • JSON-Based Serialized LOB Pattern
  • How To Check for JSON Insecure Deserialization (JID) Attacks With Java
  • What Is Ant, Really?
  • Apache Spark 3 to Apache Spark 4 Migration: What Breaks, What Improves, What's Mandatory

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook