简体   繁体   English

Jackson 反序列化对象为同一个

[英]Jackson deserialize objects as the same one

I was working with jackson's JsonIdentityInfo annatation, the serialization looks good.我正在使用杰克逊的JsonIdentityInfo注释,序列化看起来不错。 But the deserialization didnt work as I expected, the objects sharing the same id, are not deserialized into the same objects.但是反序列化没有像我预期的那样工作,共享相同 id 的对象没有反序列化为相同的对象。 Below are the class definitions.以下是 class 定义。

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
    }

Deserialization creates new objects from JSON.反序列化从 JSON 创建新对象。 Objects sharing the same id are deserialized into the same objects.共享相同 id 的对象被反序列化为相同的对象。 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 .请注意第二个参数listD.get(1).p中的“D”。

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

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