Reputation: 101
I'm currently trying to implement a PATCH endpoint that should only change values that are actually provided in the JSON Post Body. Unfortunately, it looks like Jackson is treating non-provided values as NULL though, thus resetting those existing values. Following example:
public class Item {
@Id @GeneratedValue
private Long id;
private String name;
//getters+setters
}
and the according Controller:
@RequestMapping(value = /item/{id}, method = RequestMethod.PATCH)
public ResponseEntity<Item> patchItem(@PathVariable("id") Long itemId, @RequestBody Item item) {
if (itemRepository.exists(itemId) && item.getId().equals(itemId)) {
Item newItem = itemRepository.save(item);
return new ResponseEntity<>(newItem, HttpStatus.OK);
}
throw new ResourceNotFoundException("could not find Item with id " + itemId);
}
When I call to that endpoint now with just the ID provided, I want the existing name NOT to be nulled:
PATCH to /item/1 with postbody { "id":1 }
should result in
{
"id":1,
"name":"value_before_patch"
}
and not in { "id":1 }
(name not provided because of builder.serializationInclusion(JsonInclude.Include.NON_NULL);)
as it is now.
How do I need to configure Jackson to achieve that?
Upvotes: 0
Views: 790
Reputation: 2043
Maybe there's something I don't understand in the question, but : if you provide an incomplete object representation in JSON, the resulting fields in java will be null. How could it be different from that? When you save the (incomplete) deserialized object, the fields that weren't specified in JSON will be nullified. You can't do anything about that. What you could do is check each and every field on the java object you're about to save, and put the old value in every null field.
As a side note, this is the reason (afaict) PATCH is not a common service, i.e. it is quite hard to implement particularly if you have complex objects.
Edit :
I didn't knew about the json-patch
proposed standard. This could be a solution to what you are trying to achieve. I'd suggest you take a look at this tutorial on how to integrate it with Jersey, or even at the rfc (6902). In a nutshell, json-patch formalizes how you can send commands (patches) to selectively modify an object. An example is the following :
given an object whose json initial representation is
{
"list" : [
"one",
"two"
],
"message" : "message",
"title" : "title"
}
You can patch it with a json like
[
{
"op" : "replace",
"path" : "/message",
"value" : "otherMessage"
},
{
"op" : "add",
"path" : "/list/-",
"value" : "three"
}
]
Hope this can help.
Upvotes: 1