使用Jackson

时间:2015-09-03 13:28:12

标签: java json serialization jackson deserialization

我有这两个类:

@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;
    }

    ...
}

我尝试按以下方式序列化和反序列化用户对象

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);

和JsonMappingException:已经生成了用于id的POJO。的为什么吗

当我查看序列化的json结果时,我看到结果是

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

结果应为

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

因为rol1和rol2是ID为1的相同POJO标识符的不同实例。

如何避免JsonMappingException?在我的项目中,我有一些相同POJO的不同实例。如果内容相同,我可以保证 - &gt;对象是平等的。

请原谅我的英语不好。

2 个答案:

答案 0 :(得分:2)

对于回到此问题的任何人来说,看起来可以选择使用Jackson中的自定义ObjectIdResolver执行此操作。您可以在@JsonIdentityInfo注释上指定它,例如:

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

然后可能包装正常的SimpleObjectIdResolver类以开始并自定义bindItem()。

在我的情况下,我想避免重叠objectIds,所以在我开始新的东西时清除了引用:

    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();
        }
    }

答案 1 :(得分:0)

对于不同的类实例,杰克逊预计在这种情况下会有不同的id。先前在github here进行了讨论。覆盖hashCodeequals无济于事。对象引用必须匹配相等的id

选项

  1. 重用Rol个实例,而不是使用相等字段创建新实例。作为奖励,您还可以节省内存。
  2. 修改应用程序逻辑,使其不依赖于@JsonIdentityInfo