JSON Jackson parse different keys into same field

JavaJsonJackson

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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));

    }
}

Solution 3 - Java

I'd propose to use getters/setters, for both property names, which are referring to the same POJO field.

public class Media {
    private Asset asset;
  
    @JsonProperty("cover_asset")
    public Asset getCoverAsset() {
      return asset;
    }

    public void setCoverAsset(Asset asset) {
      this.asset= asset;
    }

    @JsonProperty("asset")
    public Asset getAsset() {
      return asset;
    }

    public void setAsset(Asset asset) {
      this.asset= asset;
    }
}

See also my answer to possible duplicate question: https://stackoverflow.com/questions/8560348/different-names-of-json-property-during-serialization-and-deserialization/8560390#8560390

Solution 4 - Java

Great answer By Vikas with JsonAlias.

Just adding that you can also benefit from both of the worlds (JsonProperty&Alias) [Since jackson 2.9]:

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

Reference.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDArkOView Question on Stackoverflow
Solution 1 - JavaVikas PrasadView Answer on Stackoverflow
Solution 2 - JavawhaleyView Answer on Stackoverflow
Solution 3 - JavaDRCBView Answer on Stackoverflow
Solution 4 - JavaRobocideView Answer on Stackoverflow