Problem with ObjectIds
heruan opened this issue · 2 comments
Patching and deserializing object annotated with JsonIdentityInfo may fail when duplicate ids occur. For example, given a JSON source:
{
"@id": 123,
"name": "John",
"dog": { "@id": 456, "name": "Buddy" },
"cat": { "@id": 789, "name": "Rover" },
"favoritePet": 456
}applying
[ {
"op": "replace",
"path": "/favoritePet",
"value": { "@id": 789, "name": "Rover" }
} ]will result in
{
"@id": 123,
"name": "John",
"dog": { "@id": 456, "name": "Buddy" },
"cat": { "@id": 789, "name": "Rover" },
"favoritePet": { "@id": 789, "name": "Rover" }
}and deserializing with Jackson will fail with:
JsonMappingException: Already had POJO for id '789'
The patch is applied correctly, but it cannot be deserialized as a side effect of duplicated ObjectIds. Id would be useful to have JsonPatch recognize ObjectIds and use them if the patched JSON already contains one.
Despite being a java implementation of json-patch, json-patch itself is a broader internet standard. Not sure if adding something in to support a deserialization framework like Jackson is the right direction. I could be misunderstanding.
That's true, it may be an additional plugin. I managed to achieve the desired result with a simple for-loop:
JsonNode patchedState = jsonPatch.apply(currentState);
Set<String> visited = new HashSet<>();
for (JsonNode node : patchedState.findParents("@id")) {
String identity = node.get("@id").asText();
ObjectNode objectNode = (ObjectNode) node;
if (visited.contains(identity)) {
objectNode.removeAll();
objectNode.put("@ref", identity);
} else {
visited.add(identity);
}
}This works when the ObjectId generator is JSOG-compliant.