Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing JSON Merge Patch in ASP.NET Core WebAPI

I am interested in adding support for partial updates in my ASP.NET Core WebAPI where I only update the properties on a resource that the caller provided, leaving excluded properties unchanged.

For context, imagine I have a resource that can be described as follows:

GET /users/1
{
    title: "Mister",
    firstName: "Frederick",
    middleName: "McFeely",
    lastName: "Rodgers"
}

If I wanted to allow consumers to change the value stored in the firstName property from "Frederick" to "Fred" in isolation, I should be able to expose a PATCH endpoint that supports the JSON Merge Patch Content-Type, like so:

PATCH /users/1
Content-Type: application/merge-patch+json
{
    firstName: "Fred"
}

However, I see no easy way for me to know that firstName is the only property being updated. For example, if I were to make a controller that accepted PATCH verbs, it could be scaffolded like this:

[Route("users")]
public class UsersController : Controller {

    [HttpPatch("{userId:int}")]
    public User Patch([FromRoute] int userId, [FromBody] User user) {

        // How do I know which properties were set on User at this point?

    }

}

public class User {

    public String Title { get; set; }
    public String FirstName { get; set; }
    public String MiddleName { get; set; }
    public String LastName { get; set; }

}

But I don't see how I can extract which properties' had keys defined on the JSON object before it was hydrated as a User and passed to my controller. I cannot assume a value of null to mean a property was excluded as the caller could be explicitly setting an optional property to null.

Edit

I am aware of the Microsoft.AspNetCore.JsonPatch library. This, unfortunately, expects the caller to use the "[description of changes]" to define a PATCH as described in RFC 5789, which I find unintuitive and verbose. I am referring to the "JSON Merge Patch" defined in RFC 7396.

like image 560
Technetium Avatar asked Sep 14 '17 03:09

Technetium


People also ask

What is JSON merge patch?

A JSON merge patch document describes changes to be made to a target JSON document using a syntax that closely mimics the document being modified.

How do I use Web API patch?

HTTP POST can support partial updates to a resource. But there is a separate PATCH method. This new HTTP method, PATCH, modifies an existing HTTP resource. The call to the Patch method is sufficient to partially update the corresponding properties of the Employee object in the list.

How does JSON Patch work?

How it works. A JSON Patch document is just a JSON file containing an array of patch operations. The patch operations supported by JSON Patch are “add”, “remove”, “replace”, “move”, “copy” and “test”. The operations are applied in order: if any of them fail then the whole patch operation should abort.

What is JSON merge?

json-merge is a library allowing you to merge two json files for the JVM written in Kotlin. It currently supports two modes for merging arrays and objects.


1 Answers

for simple types, I found a very simple solution using Newtonsoft.Json merge of JObjects:

public static T Patched<T>(T source, JObject patch) where T : class
{
    var sourceObject = JObject.FromObject(source);
    sourceObject.Merge(patch, new JsonMergeSettings() {MergeArrayHandling = MergeArrayHandling.Union});
    return sourceObject.ToObject<T>();
}

public static T Patched<T>(T source, string patchCode) where T : class
{
    return Patched<T>(source, JObject.Parse(patchCode));
}

Hope this helps someone searching for this topic and looking for a simple solution without external packages.

like image 148
Claas Diederichs Avatar answered Oct 05 '22 21:10

Claas Diederichs