Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON Jackson parse different keys into same field

Tags:

java

json

jackson

I have a POJO which has a field:

public class Media {  private Asset asset; } 

Everything works perfectly when parsing a json response into this asset POJO. but however there is a slight difference with the key this asset comes with. It can either be:

  @JsonProperty("cover_asset") 

or

  @JsonProperty("asset") 

Is there a way to annotate the POJO to recognize this case and de-serialize into the same field. Its not possible for both of them to appear in the same response.

like image 599
DArkO Avatar asked Oct 24 '13 11:10

DArkO


People also ask

What is the difference between JsonProperty and JsonAlias?

@JsonProperty can change the visibility of logical property using its access element during serialization and deserialization of JSON. @JsonAlias defines one or more alternative names for a property to be accepted during deserialization.

What is the use of JsonAlias?

The @JsonAlias annotation can define one or more alternate names for the attributes accepted during the deserialization, setting the JSON data to a Java object. But when serializing, i.e. getting JSON from a Java object, only the actual logical property name is used instead of the alias.

How does Jackson parse JSON?

databind. ObjectMapper ) is the simplest way to parse JSON with Jackson. The Jackson ObjectMapper can parse JSON from a string, stream or file, and create a Java object or object graph representing the parsed JSON. Parsing JSON into Java objects is also referred to as to deserialize Java objects from JSON.


Video Answer


2 Answers

Well, as only deserialization is your concern, @JsonAlias introduced in 2.9 is perfect for this situation. You can do something like this:

@JsonAlias({"cover_asset", "asset"}) private Asset asset; 

@JsonAlias docs:

Annotation that can be used to define one or more alternative names for a property, accepted during deserialization as alternative to the official name. Alias information is also exposed during POJO introspection, but has no effect during serialization where primary name is always used.

Note: Make sure you update all related dependencies(annotations, core, databind) if you are using them. Updating just annotations without others threw me runtime error.

like image 72
Vikas Prasad Avatar answered Sep 21 '22 17:09

Vikas Prasad


More succinctly, I would suggest using two separate @JsonSetter annotations for this. Here's a working example. This means that your java class will only have one getter method to use for the property instead of two. You can also make the setter you don't want exposed to clients of Media private and treat one of the json keys in a special manner.

import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.ObjectMapper;  @SuppressWarnings("unused") public class Media {      private Asset asset;      @JsonGetter("asset")     public Asset getAsset() {         return asset;     }      @JsonSetter("asset")     public void setAsset(Asset asset) {         this.asset = asset;     }      @JsonSetter("cover_asset")     private void setMediaAsset(Asset asset) {         if (this.asset == null) {             setAsset(asset);         }     }       private static class Asset {         @JsonProperty("foo")         private String foo;     }      public static void main(String[] args) throws Exception {         String withAsset = "{'asset': {'foo':'bar'}}";         String withCoverAsset = "{'cover_asset': {'foo':'bar'}}";          ObjectMapper mapper = new ObjectMapper();         Media mediaFromAsset = mapper.readValue(withAsset.replace('\'','"'), Media.class);         Media mediaFromCoverAsset = mapper.readValue(withCoverAsset.replace('\'','"'), Media.class);          System.out.println(mediaFromAsset.asset.foo.equals(mediaFromCoverAsset.asset.foo));      } } 
like image 36
whaley Avatar answered Sep 19 '22 17:09

whaley