Jackson deserialization with unknown dynamic properties

jackson, java, json

Solution

Your `shipping_profiles` property doesn't look like array. It represent object with dynamic properties, so we should treat it like an object. If we do not know anything about properties we can use `@JsonAnySetter` annotation. Algorithm could looks like below:

- Deserialize JSON into JSON-model classes.

- Convert dynamic objects (maps) into app's POJO classes using ObjectMapper

- Use app's POJO whenever you want.

Please see my example implementation. I hope, it help you solve your problem. Input JSON:

{
   "shipping_profiles":{
      "563":{
         "name":"name563",
         "value":"value563"
      },
      "564":{
         "name":"name564",
         "value":"value564"
      },
      "565":{
         "name":"name565",
         "value":"value565"
      },
      "566":{
         "name":"name566",
         "value":"value566"
      }
   }
}

Example program:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonProgram {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        File source = new File("X:/test.json");
        Entity entity = mapper.readValue(source, Entity.class);
        ShippingProfiles shippingProfiles = entity.getShippingProfiles();
        List<Map<String, String>> profileMaps = shippingProfiles.getProfiles();

        List<Profile> profiles = new ArrayList<Profile>(profileMaps.size());
        for (Map<String, String> item : profileMaps) {
            profiles.add(mapper.convertValue(item, Profile.class));
        }
        System.out.println(profiles);
    }
}

class Entity {

    @JsonProperty("shipping_profiles")
    private ShippingProfiles shippingProfiles;

    public ShippingProfiles getShippingProfiles() {
        return shippingProfiles;
    }

    public void setShippingProfiles(ShippingProfiles shippingProfiles) {
        this.shippingProfiles = shippingProfiles;
    }
}

class ShippingProfiles {

    private List<Map<String, String>> profiles = new ArrayList<Map<String, String>>();

    @JsonAnySetter
    public void setDynamicProperty(String name, Map<String, String> map) {
        profiles.add(map);
    }

    public List<Map<String, String>> getProfiles() {
        return profiles;
    }

    public void setProfiles(List<Map<String, String>> profiles) {
        this.profiles = profiles;
    }
}

class Profile {

    private String name;
    private String value;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Profile [name=" + name + ", value=" + value + "]";
    }
}

Above app prints:

[Profile [name=name563, value=value563], Profile [name=name564, value=value564], Profile [name=name565, value=value565], Profile [name=name566, value=value566]]

Problem

I have a JSON string like: ``` "shipping_profiles": { "563": { "name": "name", "value": "value" }, "564": { "name": "name", "value": "value" }, "565": { "name": "name", "value": "value" }, "566": { "name": "name", "value": "value" } } ``` Now I am parsing it with Jackson 2.0. I am trying to get a `List<shipping_profiles>` from the JSON string. Is it possible?

Original source