json - 从杰克逊的一个对象到另一个对象的深层属性副本?
问题描述
我正在执行 UPDATE 操作,以便non-null
将传入 POJO 中设置的所有属性复制到另一个对象(相同类型)中,嵌套属性也会发生这种情况。
前任:
POJO:
public class Person {
private String homePhoneNumber;
private String officePhoneNumber;
private Address address;
public String getHomePhoneNumber() {
return homePhoneNumber;
}
// getter/setters
}
public class Address {
private String street;
private String houseNumber;
public String getStreet() {
return street;
}
// getter/setters
}
// Source
Person sourcePerson = new Person();
sourcePerson.setHomePhone("123");
Address address1 = new Address();
address1.setStreet("Street");
sourcePerson.setAddress(address1);
//Dest person
Person destPerson = new Person();
destPerson.setOfficePhone("456");
destPerson.setHomePhone("123");
Address address2 = new Address();
address2.setStreet("Street2");
address2.setHouseNumber("246");
destPerson.setAddress(address2);
ObjectMapper mapper = new ObjectMapper();
//skip setters for null values
mapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP));
Person result = mapper.updateValue(destPerson, sourcePerson);
所以我想复制所有non-null
设置的属性sourcePerson
以获取复制,destPerson
即仅覆盖已设置的那些属性destperson
,sourcePerson
保持其他属性不变。
使用
Person result = mapper.updateValue(destPerson, sourcePerson);
不适用于嵌套属性。它将整个Address
对象从源替换到目的地
我搜索了杰克逊以找到杰克逊的merge
功能:
mapper.setDefaultMergeable(true);
但是,添加此配置会使 in 中的null
值也sourcePerson
使那些 in 无效destPerson
,这似乎很奇怪。
mapper.configOverride(Address.class).setMergeable(true);
上面的配置适用于我想要的。但是我有很多 POJO 嵌套资源,所以我不想要每个 POJO 的特定配置。
这可以用jackson
干净的方式实现吗?
解决方案
您可以首先启用关于合并的错误报告
com.fasterxml.jackson.databind.MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE
这必须是假的。
这种作品确实很奇怪mapper.configOverride()
,但不是mapper.setDefaultMergeable()
。
在您的示例中,我没有看到二传手。你不是在课堂上使用@JsonSetter
注释吗?Person
然后他们将覆盖映射器配置。
在jackson-databind单元测试中,我看到他们正在使用mapper.readerForUpdating()
而不是mapper.updateValue()
:
private final ObjectMapper MAPPER = objectMapperBuilder()
// 26-Oct-2016, tatu: Make sure we'll report merge problems by default
.disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
.build();
public void testBeanMergingWithNullDefault() throws Exception
{
// By default `null` should simply overwrite value
ConfigDefault config = MAPPER.readerForUpdating(new ConfigDefault(5, 7))
.readValue(aposToQuotes("{'loc':null}"));
assertNotNull(config);
assertNull(config.loc);
// but it should be possible to override setting to, say, skip
// First: via specific type override
// important! We'll specify for value type to be merged
ObjectMapper mapper = newObjectMapper();
mapper.configOverride(AB.class)
.setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP));
config = mapper.readerForUpdating(new ConfigDefault(137, -3))
.readValue(aposToQuotes("{'loc':null}"));
assertNotNull(config.loc);
assertEquals(137, config.loc.a);
assertEquals(-3, config.loc.b);
// Second: by global defaults
mapper = newObjectMapper();
mapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP));
config = mapper.readerForUpdating(new ConfigDefault(12, 34))
.readValue(aposToQuotes("{'loc':null}"));
assertNotNull(config.loc);
assertEquals(12, config.loc.a);
assertEquals(34, config.loc.b);
}
也值得尝试com.fasterxml.jackson.annotation.JsonMerge
直接在Person
课堂上使用。
推荐阅读
- deep-learning - 在带有 OpenCL 1.1 EP 的 Vivante GC2000 GPU 上是否有任何用于 CNN 的推理引擎?
- python - 如何检查对象是否存在(Selenium/Python)并执行 if-else
- javascript - 引导日期选择器禁用特定日期
- dagger-2 - 带有即时应用程序的匕首 2
- php - 如何将裁剪的图像从 Ajax 发送到 Symfony 控制器?
- r - ggplot (R) 中的第二个 Y 轴
- c++ - 为什么 cin 不在 for 循环中执行?
- python - Python - 如何通过其兄弟内容在 Selenium Webdriver 中查找元素?
- android - 推送通知仅适用于外国第三方推送提供商服务?
- go - 如果发生条件,停止读取频道的最佳方法