FasterXML / FasterXML/jackson-databind

Allow handling of unresolved forward references when using @JsonIdentityInfo(resolver = ..)

Abierto
#670 0 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Java
Estrellas
3.7k
Forks
1.5k
Merge medio
3 d 6 h
PR fusionados (30 d)
28

Descripción

I commonly use @JsonIdentityReference(alwaysAsId = true) and @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", resolver = MyClassIdResolver.class) for my JSON entities. Ember data requires ids only and sends ids only. But I am also implementing a backup endpoint that will get (almost) fully linked nested object representation in the form of.

```
{
articles: [
{"id": 1, "posts": [2, 3]}
],
posts: [
{"id": 2, "article": 1},
{"id": 3, "article": 1}
]
}
```

The default com.fasterxml.jackson.annotation.SimpleObjectIdResolver works like a charm when all is resolvable using the received JSON so the backup part is working well.

Unfortunately it fails with the usual unresolved forward reference when something is missing in the JSON, but is known in the database...

```
HTTP POST to /posts as executed by Ember data
{
"article": 1,
"title": "something"
}
```

I tried to solve this by creating a custom id resolver (see the bottom of the report) and encountered a show stopper issue. The id is being resolved at the moment when it is encountered in the received data and that means before Jackson itself tried to resolve the existing forward references. So my resolver creates a dummy empty object with Id and then fails, because Jackson encounters the provided item with the same id and calls bindItem.

I would like to ask for an handleUnresolved argument to JsonIdentityInfo that would allow me to handle (create) dummy objects only for the ids that were still left unresolved after the forward reference relinking happened. That way both my backup and item based API will work properly.

The resolver I used:

```
public abstract class AbstractIdResolver implements ObjectIdResolver {
private Map _items = new HashMap();

@Override
public void bindItem(ObjectIdGenerator.IdKey id, Object ob)
{
if (_items.containsKey(id)) {
throw new IllegalStateException("Already had POJO for id (" + id.key.getClass().getName() + ") [" + id
+ "]");
}
_items.put(id, ob);
}

@Override
public Object resolveId(ObjectIdGenerator.IdKey id) {
Object obj = _items.get(id);
if (obj == null) {
obj = create(id);
_items.put(id, obj);
}
return obj;
}

public Object create(ObjectIdGenerator.IdKey id) {
try {
System.out.println("Creating empty " +getType().getName()+ " with id "+id.key.toString());
return getType().getConstructor(id.key.getClass()).newInstance(id.key);
} catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException|InstantiationException ex) {
ex.printStackTrace();
return null;
}
}

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

protected abstract Class getType();

@Override
public ObjectIdResolver newForDeserialization(Object c) {
return this;
}

}
```

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.