英文:
Jackson deserialize objects as the same one
问题
以下是您要翻译的内容:
我使用Jackson的JsonIdentityInfo
注解进行工作,序列化看起来很好。但反序列化并没有按照我预期的方式工作,具有相同id的对象未反序列化为相同的对象。以下是类定义。
class ParameterResolver implements ObjectIdResolver {
private final Map<ObjectIdGenerator.IdKey, Object> items = new HashMap<>();
@Override
public void bindItem(ObjectIdGenerator.IdKey id, Object pojo) {
if (items.containsKey(id)) {
throw new IllegalStateException("已经有了id为 (" + id.key.getClass().getName() + ") [" + id + "]");
}
items.put(id, pojo);
}
@Override
public Object resolveId(ObjectIdGenerator.IdKey id) {
Object object = items.get(id);
return object == null ? getById(id) : object;
}
protected Object getById(ObjectIdGenerator.IdKey id) {
Object object;
try {
object = id.scope.getConstructor().newInstance();
id.scope.getMethod("setId", Integer.class).invoke(object, (Integer) id.key);
} catch (Exception e) {
throw new IllegalStateException(e);
}
items.put(id, object);
return object;
}
@Override
public ObjectIdResolver newForDeserialization(Object context) {
return new ParameterResolver();
}
@Override
public boolean canUseFor(ObjectIdResolver resolverType) {
return resolverType.getClass() == getClass();
}
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, resolver = ParameterResolver.class, property = "id", scope = Parameter.class)
class Parameter {
private Integer id;
private String data;
public Parameter() {}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
class Container {
public Parameter p;
public Container() {}
public Container(Parameter p) {
this.p = p;
}
}
这是单元测试:
@Test
public void test() throws JsonProcessingException {
Parameter p1 = new Parameter(), p2 = new Parameter();
p1.setId(1);
p1.setData("1");
List<Container> list = new ArrayList<>();
list.add(new Container(p1));
list.add(new Container(p1));
ObjectMapper mapper = new ObjectMapper();
String content = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
List<Container> listD = mapper.readValue(content, new TypeReference<List<Container>>() {});
assertSame(listD.get(0).p, list.get(1).p); // 没有通过此断言
}
英文:
I was working with jackson's JsonIdentityInfo
annatation, the serialization looks good. But the deserialization didnt work as I expected, the objects sharing the same id, are not deserialized into the same objects. Below are the class definitions.
class ParameterResolver implements ObjectIdResolver {
private final Map<ObjectIdGenerator.IdKey,Object> items = new HashMap<>();
@Override
public void bindItem(ObjectIdGenerator.IdKey id, Object pojo) {
if (items.containsKey(id)) {
throw new IllegalStateException("Already had POJO for id (" + id.key.getClass().getName() + ") [" + id
+ "]");
}
items.put(id, pojo);
}
@Override
public Object resolveId(ObjectIdGenerator.IdKey id) {
Object object = items.get(id);
return object == null ? getById(id) : object;
}
protected Object getById(ObjectIdGenerator.IdKey id){
Object object;
try {
object = id.scope.getConstructor().newInstance();
id.scope.getMethod("setId", Integer.class).invoke(object, (Integer) id.key);
} catch (Exception e) {
throw new IllegalStateException(e);
}
items.put(id, object);
return object;
}
@Override
public ObjectIdResolver newForDeserialization(Object context) {
return new ParameterResolver();
}
@Override
public boolean canUseFor(ObjectIdResolver resolverType) {
return resolverType.getClass() == getClass();
}
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, resolver = ParameterResolver.class, property = "id", scope = Parameter.class)
class Parameter {
private Integer id;
private String data;
public Parameter() {}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
class Container {
public Parameter p;
public Container() {}
public Container(Parameter p) {
this.p = p;
}
}
and this is the unit test
@Test
public void test() throws JsonProcessingException {
Parameter p1 = new Parameter(), p2 = new Parameter();
p1.setId(1);
p1.setData("1");
List<Container> list = new ArrayList<>();
list.add(new Container(p1));
list.add(new Container(p1));
ObjectMapper mapper = new ObjectMapper();
String content = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
List<Container> listD = mapper.readValue(content, new TypeReference<List<Container>>() {});
assertSame(listD.get(0).p, list.get(1).p); // didnt pass this assertion
}
答案1
得分: 2
反序列化从JSON创建新对象。共享相同id的对象被反序列化为相同的对象。然而,这些对象与先前序列化的对象不同。
在您的断言中,您正在比较一个反序列化的参数实例与用于序列化的实例:
assertSame(listD.get(0).p, list.get(1).p); // 这个断言未通过
您应该比较两个反序列化的实例:
assertSame(listD.get(0).p, listD.get(1).p);
请注意第二个参数listD.get(1).p
中的' D '。
英文:
Deserialization creates new objects from JSON. Objects sharing the same id are deserialized into the same objects. However, these are different objects than those that were previously serialized.
In your assertion you are comparing a deserialized parameter instance with an instance that was used for serialization:
assertSame(listD.get(0).p, list.get(1).p); // didnt pass this assertion
You should compare the two deserialized instances instead:
assertSame(listD.get(0).p, listD.get(1).p);
Please note the 'D' in the second parameter listD.get(1).p
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论