Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson deserialization with unknown dynamic properties

Tags:

java

json

jackson

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?

like image 595
Tanmay Mandal Avatar asked Jul 16 '13 19:07

Tanmay Mandal


People also ask

Does Jackson ignore unknown properties?

This time also it will work because Jackson is ignoring all unknown properties. That's all about how to ignore unknown properties while parsing JSON in Java using Jackson API.

How do I ignore properties in Jackson?

The Jackson @JsonIgnore annotation can be used to ignore a certain property or field of a Java object. The property can be ignored both when reading JSON into Java objects and when writing Java objects into JSON.

How do I ignore properties in ObjectMapper?

ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); objectMapper. configure(DeserializationFeature. FAIL_ON_UNKNOWN_PROPERTIES, false); Note: Unknown properties will be ignored by this for any JSON it's going to parse.

How do you tell Jackson to ignore a field during deserialization?

Overview So when Jackson is reading from JSON string, it will read the property and put into the target object. But when Jackson attempts to serialize the object, it will ignore the property. For this purpose, we'll use @JsonIgnore and @JsonIgnoreProperties.


1 Answers

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:

  1. Deserialize JSON into JSON-model classes.
  2. Convert dynamic objects (maps) into app's POJO classes using ObjectMapper
  3. 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]]
like image 70
Michał Ziober Avatar answered Sep 23 '22 08:09

Michał Ziober