Search code examples
javaspringjacksonjackson-databind

How do I unmarshal a dynamic type from JSON with Spring RestTemplate and Jackson


I have a JSON response coming from an API that is calling Elastic Search. The following is a sample snippet.

{
  "fielda" : "something",
  "hits" : {
    "total" : "100",
    "type" : "/some/type"
    "dynamicAttributes":{
       "somevalue1" : "somevalue",
       "somevalue2" : "somevalue2"
    }
  }
}

The JSON subtree underneath the dynamicAttributes can be different with each result. I am trying to marshal that into an object based on the type field that comes in. There will be an established mapping between that value and a class somewhere in a map. It looks like Jackson maps the results into a LinkedHashMap if the type is not resolved. I'm looking to use a Custom Deserializer. Is this the best strategy for this? Or is there something simpler that I'm missing.


Solution

  • You can use @JsonTypeInfo and @JsonSubType annotations to marshal the given input.

    On your dynamicAttributes field you can add a JsonTypeInfo annotation to specify how to create a dynamicAttribute's object. The EXTERNAL_PROPERTY type conveys that the type field is present at the level of dynamicAttributes.

      @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property ="type", include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
          visible = true)
      DynamicAttributes dynamicAttributes;
    

    To specify the possible subtypes use the JsonSubTypes annotation as shown below

    @JsonSubTypes({
      @JsonSubTypes.Type(value = DynamicAttributesType1.class, name = "type1")
      , @JsonSubTypes.Type(value = DynamicAttributesType2.class, name = "type2")
    })
    public abstract class DynamicAttributes{
    }