简体   繁体   English

使用 Jackson 序列化两个具有相同 id 的不同 POJO 对象

[英]Serialize two different POJO object with the same id with Jackson

I have these two classes:我有这两个类:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id",scope = Rol.class)
public class Rol extends MyEntity implements Serializable {
    private Integer id;
    private String rolName;

    public Rol(Integer id, String rolName) {
        this.id = id;
        this.rolName = rolName;
    }

    ...
}

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id",scope = User.class)
public class User extends MyEntity implements Serializable {
    private Integer id;
    private String name;
    private List<Rol> rolList;

    public User(Integer id, String name, List<Rol> rolList) {
        this.id = id;
        this.name = name;
        this.rolList = rolList;
    }

    ...
}

and I try to serialize and deserialize the user object as following我尝试序列化和反序列化用户对象如下

Rol rol1 = new Rol(1, "MyRol");
Rol rol2 = new Rol(1, "MyRol");
List<Rol> rolList = new ArrayList();
rolList.add(rol1);
rolList.add(rol2);

user = new User(1, "MyUser", rolList);

ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(user);
User userJson = mappe.readValue(jsonString, User.class);

and the JsonMappingException: Already had POJO for id is produced.并且 JsonMappingException: Already have POJO for id 已生成。 Why?为什么?

When I review the json result of the serialization I see that the result is当我查看序列化的 json 结果时,我看到结果是

{"id": 1,"name": "MyName","rolList": [{"id": 1,"rolName": "MyRol"},{"id": 1,"rolName": "MyRol"}]}

when the result should be结果应该是什么时候

{"id": 1,"name": "MyName","rolList": [{"id": 1,"rolName": "MyRol"},1]}

because rol1 and rol2 are different instances of the same POJO identifier with id 1.因为 rol1 和 rol2 是 id 为 1 的同一个 POJO 标识符的不同实例。

How can I avoid the JsonMappingException?如何避免 JsonMappingException? In my project I have some different instances of the same POJO.在我的项目中,我有一些相同 POJO 的不同实例。 I can guarantee that if the id's are equal -> objects are equal.我可以保证,如果 id 是相等的 -> 对象是相等的。

Excuse me for my bad English.请原谅我的英语不好。

For anyone returning to this question, it looks like there's option to do this with a custom ObjectIdResolver in Jackson.对于任何返回此问题的人,似乎可以选择使用 Jackson 中的自定义 ObjectIdResolver 来执行此操作。 You can specify this on the @JsonIdentityInfo annotation, eg :您可以在 @JsonIdentityInfo 注释上指定它,例如:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name", 
    resolver = CustomObjectIdResolver.class)

Then perhaps wrap the normal SimpleObjectIdResolver class to get going and customise bindItem().然后也许包装正常的 SimpleObjectIdResolver 类以开始并自定义 bindItem()。

In my case I wanted to avoid overlapping objectIds, so cleared down the references when I started a new Something:在我的例子中,我想避免重叠 objectId,所以当我开始一个新的东西时清除引用:

    public class CustomObjectIdResolver implements ObjectIdResolver {
        private ObjectIdResolver objectIdResolver;

        public CustomObjectIdResolver() {
            clearReferences();
        }

        @Override
        public void bindItem(IdKey id, Object pojo) {
            // Time to drop the references?
            if (pojo instanceof Something)
                clearReferences();

            objectIdResolver.bindItem(id, pojo);
        }

        @Override
        public Object resolveId(IdKey id) {
            return objectIdResolver.resolveId(id);
        }

        @Override
        public boolean canUseFor(ObjectIdResolver resolverType) {
            return resolverType.getClass() == getClass();
        }

        @Override
        public ObjectIdResolver newForDeserialization(Object context) {
            return new CustomObjectIdResolver();
        }

        private void clearReferences() {
            objectIdResolver = new SimpleObjectIdResolver();
        }
    }

Jackson expects in this case different id for different class instances.在这种情况下,杰克逊期望不同的类实例有不同的id There has been a previous discussion at github here .之前在 github这里有过讨论。 Overriding hashCode and equals will not help.覆盖hashCodeequals将无济于事。 Object references must match for equal id .对象引用必须匹配相等的id

Options选项

  1. Reuse Rol instances instead of making new ones with equal fields.重用Rol实例而不是创建具有相同字段的新实例。 As a bonus you will also save memory.作为奖励,您还可以节省内存。
  2. Modify the application logic so that it doesn't depend on @JsonIdentityInfo修改应用逻辑,使其不依赖于@JsonIdentityInfo

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

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