Reputation: 87
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
}
Upvotes: 0
Views: 533
Reputation: 27126
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
.
Upvotes: 2