Deserializing JSON Object With Unknown Properties

As a back-end developer, consuming JSON objects is pretty much very common. I think it is second only to publishing data in JSON format, the other end of what is usually a 2-way street. We may have a REST API endpoint that accepts orders for an online food delivery service that takes in JSON formatted data. Perhaps you have a client application that subscribes to a message streaming service where the payload is, again, JSON. The thing is that JSON is quite ubiquitous when it comes to transferring data over the wire for as long as I can remember.

Most of the time we know what the payload format would look like. We know what to expect. It can be validated against, or have some defaults in place. If it fails for lacking a mandatory field, we can always throw an error. That is fine. Majority of the time that is what happens.

Whether we have full, partial or no control whatsoever of what is ingested for processing, there will be instances where in the data that comes in is not what is expected. Instead of 5 fields in the JSON object, there is an extra field, or two, in there and we don’t know what it is. What do I do about it? How do I process the value for that field? Is it an integer or a string?

For me, the answer to that is – IGNORE.

Yes. Ignoring undefined fields is logical. Not always, of course. However, I don’t want my application to fail just because there was a stray integer field in there somewhere. If all the required fields are present why not let it through for processing?

As the mail analogy goes, in a post office, I cannot not deliver a letter just because the sender put in 1 extra stamp when only 2 are required. Right? With 3 stamps, 2 of which is the absolute minimum needed for it to get to its destination, it does not make sense to send it back to its origin.

Before I get carried away with all these analogies, and what not, I better start talking about what this whole article is all about.

Here, I am going to talk about a few of the usual ways to simply ignore unknown properties in a JSON object in Java using com.fasterxml.Jackson ObjectMapper.

With the Jackson library, by default parsing a JSON object with unknown properties will fail whenever it is encountered. This feature can be turned off or overridden. Here are some of the ways on how to do that.

#1 – Through class-level annotation. Everybody loves Java annotations. Maybe not? But it does make life more abstracted. We have the annotation on a class level like so:

@JsonIgnoreProperties(ignoreUnknown = true)

This pretty much says that if the property is not defined in the class, skip it! That’s all there is to it. I can go about writing the other logic that I need for my application to work on the data, without worrying if the JSON object contains other fields that I simply could not care any less.

Again, this is on a class level. I can put it in wherever I want extra properties to go away. But what if I have too many, and I just want to ignore any other fields that are not defined in my POJOs?

#2 Application-wide configuration. Whatever framework you’re using, you need to wire it accordingly, but that is up to you. Using the ObjectMapper class, I can configure it this way:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Or disable this ObjectMapper functionality altogether.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

#3 Ignore it partially. Jackson supports this through a Java Map. It will then eat up any of those undefined fields and put them all in a map of my definition. Again this is via an annotation at a class property level.

First I define a map. Then a Setter method that will take in that field as a key-value pair. Below I set the key as a String and the value as an Object. This is a fairly safe way to capture those fields that may contain nested objects or other non-String values.

private Map<String, Object> unknownProperties = new HashMap();

@JsonAnySetter
public void setUnknownProperties(String key, Object value) {
    this.unknownProperties.put(key, value);
}

The third way also allows me to log these unknown fields so I can review them later on. This becomes essential when I am consuming data from a source where I don’t have control of what’s coming in, and I want to capture as much, if not all, of that data next time.

And there you go. Three of the common ways to unmarshall that JSON object. There are other ways, like creating a custom Jackson Deserializer. This one can be used to have a more fine-grained control of parsing data, doing some transformations in-between if necessary, and finally mapping the properties out specifically.

Similar Posts: