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. Why?
When I review the json result of the serialization I see that the result is
{"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.
How can I avoid the JsonMappingException? In my project I have some different instances of the same POJO. I can guarantee that if the id's are equal -> objects are equal.
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. You can specify this on the @JsonIdentityInfo annotation, e.g. :
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name", 
    resolver = CustomObjectIdResolver.class)
Then perhaps wrap the normal SimpleObjectIdResolver class to get going and customise bindItem().
In my case I wanted to avoid overlapping objectIds, so cleared down the references when I started a new Something:
    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();
        }
    }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With