将 Json 字段包装到 pojo 的实例变量中
Wrapping Json fields into instance variable of a pojo
我正在尝试将某些 json 字段映射到 class 实例变量。
我的样本 Person class 看起来像:
public class Person {
private String name;
private Address address;
//many more fields
//getters and setters
}
样本地址class是:
public class Address {
private String street;
private String city;
//many more fields
// getters and setters
}
要反序列化为我的 Person class 的 json 对象不包含 "address" 字段。看起来像:
{
"name":"Alexander",
"street":"abc 12",
"city":"London"
}
有没有办法将 json 反序列化为地址字段也已正确映射的 Person pojo?
我使用了这里很多帖子中提到的自定义地址反序列化器。但是,它没有被调用,因为 Json 对象不包含 "address" 字段。
我已经通过使用 JsonNode 手动映射每个字段解决了这个问题,但是在我的实际项目中,这不是一个好的解决方案。
使用 jackson 可以解决此类问题吗?
另外,如果之前有人问过这个问题,那么我代表我道歉,因为我已经深入搜索了解决方案并且可能还没有看到它。 .
我不认为您真的有反序列化问题,而是一般的 Java 问题:如何确保 address
字段始终包含一个值。您需要做的就是在 Person
构造函数中将 address
分配给默认值,或者在 Person.getAddress
方法中为 address
生成并分配默认值。
我理解你的问题,所以它是关于平面 Json 的,所有 Address
字段都与 Person
处于同一级别。即使不完全是这样,这也可能对您有所帮助。 JsonDeserializer
会很好,但您需要将它应用到 Person
,因为它是所有字段所在的级别。
像这样:
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;
}
}
当然,这不是唯一的方法,也可能没有最佳性能,但这仅与您如何在自定义反序列化器中进行反序列化有关。如果您的 Person
和 Address
对象有 10 个字段,每个使用它应该不是问题。
更新
我认为在你的情况下 - 基于你的示例数据 - Michael Ziober's
answer 可能是最好的,但是如果您需要比对数据进行简单解包更复杂的处理,您只需要像我介绍的那样反序列化 Person
class。
@JsonUnwrapped
注释是针对这个问题引入的。型号:
class Person {
private String name;
@JsonUnwrapped
private Address address;
// getters, setters, toString
}
class Address {
private String street;
private String city;
// getters, setters, toString
}
用法:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Alexander\",\"street\":\"abc 12\",\"city\":\"London\"}";
System.out.println(mapper.readValue(json, Person.class));
打印:
Person{name='Alexander', address=Address{street='abc 12', city='London'}}
阅读更多信息:
我正在尝试将某些 json 字段映射到 class 实例变量。
我的样本 Person class 看起来像:
public class Person {
private String name;
private Address address;
//many more fields
//getters and setters
}
样本地址class是:
public class Address {
private String street;
private String city;
//many more fields
// getters and setters
}
要反序列化为我的 Person class 的 json 对象不包含 "address" 字段。看起来像:
{
"name":"Alexander",
"street":"abc 12",
"city":"London"
}
有没有办法将 json 反序列化为地址字段也已正确映射的 Person pojo?
我使用了这里很多帖子中提到的自定义地址反序列化器。但是,它没有被调用,因为 Json 对象不包含 "address" 字段。
我已经通过使用 JsonNode 手动映射每个字段解决了这个问题,但是在我的实际项目中,这不是一个好的解决方案。
使用 jackson 可以解决此类问题吗? 另外,如果之前有人问过这个问题,那么我代表我道歉,因为我已经深入搜索了解决方案并且可能还没有看到它。 .
我不认为您真的有反序列化问题,而是一般的 Java 问题:如何确保 address
字段始终包含一个值。您需要做的就是在 Person
构造函数中将 address
分配给默认值,或者在 Person.getAddress
方法中为 address
生成并分配默认值。
我理解你的问题,所以它是关于平面 Json 的,所有 Address
字段都与 Person
处于同一级别。即使不完全是这样,这也可能对您有所帮助。 JsonDeserializer
会很好,但您需要将它应用到 Person
,因为它是所有字段所在的级别。
像这样:
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;
}
}
当然,这不是唯一的方法,也可能没有最佳性能,但这仅与您如何在自定义反序列化器中进行反序列化有关。如果您的 Person
和 Address
对象有 10 个字段,每个使用它应该不是问题。
更新
我认为在你的情况下 - 基于你的示例数据 - Michael Ziober's
answer 可能是最好的,但是如果您需要比对数据进行简单解包更复杂的处理,您只需要像我介绍的那样反序列化 Person
class。
@JsonUnwrapped
注释是针对这个问题引入的。型号:
class Person {
private String name;
@JsonUnwrapped
private Address address;
// getters, setters, toString
}
class Address {
private String street;
private String city;
// getters, setters, toString
}
用法:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Alexander\",\"street\":\"abc 12\",\"city\":\"London\"}";
System.out.println(mapper.readValue(json, Person.class));
打印:
Person{name='Alexander', address=Address{street='abc 12', city='London'}}
阅读更多信息: