jackson-databind
jackson-databind copied to clipboard
ObjectReader support for RFC 7386 Patch Merge
Problem
I want to support JSON Patch Merge on a JSON REST API when using the PUT
HTTP Method with a Content-Type
of application/merge-patch+json
.
The current usage of ObjectMapper.readerForUpdating
does perform a merge, but it is not compliant with RFC 7386.
Some control can be had by using the @JsonMerge
field annotation, but I believe this simply allows you to control if an array is appended or overwritten with the incoming value used with the ObjectMapper.readerForUpdating
reader.
I would be happy to submit a PR (or try) -or assist in any way that I can if this is something you are willing to consider in the library.
Ideal Solution
In my usage, I will know the HTTP Method and the Content Type of the request. Using this information I would like to create a Reader that will use the merge patch rules as defined by RFC 7368.
Example usage to build a reader that is configured for Patch Merge.
// Existing object
User user = userService.retrieveUserById(42);
// New Object Mapper and reader configuration for Merge Patch
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader reader = objectMapper.readerForUpdating(user)
// New method or configuration to turn on merge strategy
.withMergeStrategy(MergeStrategy.RFC_7368);
// Merge in JSON patch
User merged = reader.readValue(request.getInputStream());
Alternatives
- Third party libraries (listed below)
- Perhaps there is a way to accomplish some basic merge / patch with the right combination of Deserialization and Serialization features on the Object Mapper.
Example Code
Using the pseudo code provided in the RFC and tests, I have stubbed out a test that passes. This is not optimal code, but maps the provided pseudo code into some (poor) semblance of Jackson code.
Test: https://github.com/prime-framework/prime-mvc/blob/f4b583fd169608d6bf8f7b0912eae60b0e71acfd/src/test/java/org/primeframework/mvc/PatchMergeTest.java#L109
Business logic for recursive patch merge: https://github.com/prime-framework/prime-mvc/blob/f4b583fd169608d6bf8f7b0912eae60b0e71acfd/src/test/java/org/primeframework/mvc/PatchMergeTest.java#L136
Additional Context
Other Java libraries that have implemented this specification in part or in full.
- https://github.com/java-json-tools/json-patch
- This library has implemented RFC 7396 using Jackson.
- https://github.com/jeffnelson/jackson-merge-patch
- This library doesn't look to be a complete drop in solution, but perhaps has some basic support.
Related Issues
https://github.com/FusionAuth/fusionauth-issues/issues/441
Looks like patch would have to operate on JsonNode
? If so, I am not sure separate merge strategy would be necessary or make sense; it might instead be possibly to simply add new merge()
method(s) in ObjectReader
and ObjectMapper
.
Although then again, I wonder if this would be better exposed as something else altogether since it appears to most easily be implemented as operation that takes in 2 JsonNode
s, and either modifying one or constructing third one.
If so, parsing of JsonNode
s can be done separately and it's just merge/patch that is separate thing.
I would also like to get something like this in place. In addition, it would be very useful to be able to create merge patches and merge diffs with Jackson. The solution above describes implementing merge patch on the server; the next logical step is to be able to call the service effectively from a client. That is what Json.createMergeDiff
does, but AFAIK there is no implementation based on Jackson.
Yes, PR would be highly welcome! I do not have bandwidth to work on this directly myself, but could help if someone else would like to do so.
I ended up using https://github.com/java-json-tools/json-patch which has worked pretty well. This library supports both RFC 6902 and 7368.
Our usage is pretty straight forward, we just bind a handler based upon the Content-Type
request header, and then handle patch or merge patch. https://github.com/prime-framework/prime-mvc/blob/efb88fd50807c86c0d9a2da33bbc476a26ad304a/src/main/java/org/primeframework/mvc/content/json/JacksonPatchContentHandler.java#L72
@fge or @Capstan any interest in porting your library into a patch here?
Thank you for update @robotdan!
I looked at the same library, but it uses a fork of jackson-coreutils and (without spending much time checking) I'm worried that it will cause problems in Quarkus with native builds. Anything not tested and supported by the Quarkus team is risky business if it uses reflection. If that library could be ported into the mainstream (and thus supported in coming Quarkus versions), it would be great.