简体   繁体   English

将Json字段包装到pojo的实例变量中

[英]Wrapping Json fields into instance variable of a pojo

i am trying to map certain json fields to a class instance variable. 我试图将某些json字段映射到类实例变量。

My sample Person class looks like: 我的示例Person类如下所示:

public class Person {
   private String name;
   private Address address;

   //many more fields 

   //getters and setters
}

The sample Address class is: 示例地址类为:

public class Address {
   private String street;
   private String city;
   //many more fields 

   // getters and setters
}

The json object to be deserialized to my Person class doesn't contain "address" field. 要反序列化到我的Person类的json对象不包含“地址”字段。 It looks like: 看起来像:

{
"name":"Alexander",
"street":"abc 12",
"city":"London"
}

Is there a way to deserialize the json to the Person pojo where the Address fields are also mapped properly? 有没有办法将json反序列化为Person pojo,其中Address字段也正确映射?

I have used a custom Address deserializer as mentioned in so many posts here. 我已经使用了自定义地址反序列化器,如此处许多文章所述。 However, it's not being called as the Json object doesn't contain "address" field. 但是,由于Json对象不包含“地址”字段,因此未调用它。

I had resolved this problem by mapping each field manually using JsonNode, however in my real project, it's not a nice solution. 我已经通过使用JsonNode手动映射每个字段解决了此问题,但是在我的真实项目中,这不是一个很好的解决方案。

Is there any work around for such problem using jackson? 使用Jackson可以解决此问题吗? Plus if this question has been asked before then apologies on my behalf as as i have intensively searched for the solution and might have not seen it yet. 另外,如果在此之前有人问过这个问题,那么我就此深表歉意,因为我一直在寻找解决方案,但可能还没有看到。 .

@JsonUnwrapped annotation was introduced for this problem. 针对此问题引入了@JsonUnwrapped注解。 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 注释类型JsonUnwrapped
  3. Jackson JSON - Using @JsonUnwrapped to serialize/deserialize properties as flattening data structure Jackson JSON-使用@JsonUnwrapped将属性序列化/反序列化为扁平化的数据结构

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. 我不认为您这里确实没有反序列化问题,而是一个普遍的Java问题:如何确保address字段始终包含一个值。 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. 所有你需要做的是无论是分配address在为默认值Person的构造,或生成并指定一个默认值addressPerson.getAddress方法。

I understood your problem so that it is about flat Json that has all Address fields at the same level as Person . 我理解了您的问题,因此有关平面Json的所有Address字段与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. JsonDeserializer会很好,但是您需要将其应用于Person因为它是所有字段所在的级别。

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. 如果您的“ PersonAddress对象具有10个字段,则每个使用此字段都不成问题。

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. 我认为在您的情况下-根据您的示例数据-MichałZiober的答案可能是最好的,但是如果您需要比普通拆包更复杂的数据处理, 则只需要像我介绍的那样反序列化Person类即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM