Wrapping Json fields into instance variable of a pojo

故事扮演 提交于 2019-12-01 23:06:15

@JsonUnwrapped annotation was introduced for this problem. Model:

class Person {
    private String name;

    @JsonUnwrapped
    private Address address;

    // getters, setters, toString
}
class Address {
    private String street;
    private String city;

    // getters, setters, toString
}

Usage:

ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Alexander\",\"street\":\"abc 12\",\"city\":\"London\"}";
System.out.println(mapper.readValue(json, Person.class));

Prints:

Person{name='Alexander', address=Address{street='abc 12', city='London'}}

For more info read:

  1. Jackson Annotation Examples
  2. Annotation Type JsonUnwrapped
  3. Jackson JSON - Using @JsonUnwrapped to serialize/deserialize properties as flattening data structure

I don't think you really have a deserialization problem here but rather a general Java problem: how to make sure the address field always contains a value. All you need to do is either assign address to a default value in the Person constructor, or generate and assign a default value for address in the Person.getAddress method.

I understood your problem so that it is about flat Json that has all Address fields at the same level as Person. Even if it is not exactly so this might help you. JsonDeserializer will do fine but you need to apply it to Person because it is the level where all the fields are.

So like this:

public class CustomDeserializer extends JsonDeserializer<Person> {

    // need to use separate ObjectMapper to prevent recursion
    // this om will not be registered with this custom deserializer
    private final ObjectMapper om;
    {
        om = new ObjectMapper();
        // this is needed because flat json contains unknown fields
        // for both types.
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public Person deserialize(JsonParser parser, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
        // make a string of json tree so not any particular object
        String json = om.readTree(parser).toString();
        // deserialize it as person (ignoring unknown fields)
        Person person = om.readValue(json, Person.class);
        // set address deserializing it from teh same string, same manner
        person.setAddress(om.readValue(json, Address.class));
        return person;
    }

}

Of course this is not the only way and might not have the best performance but it is only about how you do the deserialization in your custom deserializer. If your Person & Address objects are havin like 10 fields each using this should not be a problem.

Update

I think that in your case - based on your example data - Michał Ziober's answer might be the best but if you need any more complex handling than plain unwrapping for your data you just need to deserialize Person class somehow like I presented.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!