Dynamically Typed Object Support for JsonPatch Released

Today is a good day :-) Support for dynamics when using JsonPatch has just been released on NuGet!

Do you need this?  Read this post to find out.

First of all, a few words on what JsonPatch is:

JsonPatch (https://tools.ietf.org/html/rfc6902) defines a JSON document structure for expressing a sequence of operations to apply to a JavaScript Object Notation (JSON) document; it is suitable for use with the HTTP PATCH method. The “application/json-patch+json” media type is used to identify such patch documents.

One of the things this can be used for is partial updates for REST-ful API’s, or, to quote the IETF: “This format is also potentially useful in other cases in which it is necessary to make partial updates to a JSON document or to a data structure that has similar constraints (i.e., they can be serialized as an object or an array using the JSON grammar).

From that, Marvin.JsonPatch was born.  Today, this is extended with support for dynamics – but what is meant with that?

What is Marvin.JsonPatch.Dynamic?

The JsonPatch standard allows you to apply a set of changes to a resource.  If you map a resource (say, Person) to a .NET class, some of those changes mean changing the resource structure itself.  For example, an Add operation effectively adds fields to a resource, or, in other words: properties to a class.

That’s not possible with statically typed classes.  It is, however, possible for objects inheriting IDictionary<string, object>, like the ExpandoObject used when working with dynamically typed objects.

What this package allows is to do just that: if you apply a JsonPatchDocuments to an object that implements IDictionary<string, object> the structure of the object itself can be changed – at runtime!

Where can you get it?

Sources are on GitHub, package is on NuGet.

What is the relation to Marvin.JsonPatch & Microsoft.AspNet.JsonPatch?

Marvin.JsonPatch.Dynamic extends Marvin.JsonPatch – it thus has a dependency on Marvin.JsonPatch.  It’s packaged as a separate NuGet package because it’s no longer portable due to restrictions on what can be done with Portable Class Libraries.  It’s mainly meant to be used server-side, at API level, not at client level.

On the client side, you can use it as well if your client targets the full .NET framework.  If you’ve got a Windows Phone / Store app, Xamarin app, … talking to an API, you can use Marvin.JsonPatch on the client in combination with Marvin.JsonPatch.Dynamic at API level.

Microsoft.AspNet.JsonPatch combines both, and targets the new ASP .NET 5.  If you’re on ASP .NET 5, use that package.

How do you use it?

At client level (on full .NET), you can now create JsonPatchDocuments without knowing the class it will be applied to.  That’s a typical use case when you’re working with dynamically typed objects at API level: you might not have a shared DTO layer between your API and the client.

JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Add("Age", 34); 

// serialize
var serializedItemToUpdate = JsonConvert.SerializeObject(patchDoc); 

// create the patch request
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, "api/persons/" + id)
{
    Content = new StringContent(serializedItemToUpdate,
    System.Text.Encoding.Unicode, "application/json")
}; 

// send it, using an HttpClient instance
client.SendAsync(request);

Applying the previously created JsonPatchDocument at API level, using the ObjectAdapter from the Marvin.JsonPatch.Dynamic namespace will result in an extra property on the Person object.

The non-generic JsonPatchDocument uses this adapter by default, but if you wish, you can also pass in an instance of Marvin.JsonPatch.Dynamic.ObjectAdapter to the ApplyTo-method of the generic JsonPatchDocument.

[Route("api/expenses/{id}")]
[HttpPatch]
public IHttpActionResult Patch(int id,
[FromBody]JsonPatchDocument personPatchDocument)
{
      // get the person 
      dynamic person = _repository.GetDynamicPersonWithNameAndFirstName(id); 

      // apply the patch document 
      personPatchDocument.ApplyTo(person);
      // person now has an extra property, Age, with value 34 

}

As Marvin.JsonPatch.Dynamic is an extension to Marvin.JsonPatch, it can also be used to target any object Marvin.JsonPatch can target.

The fact that you can now also work with dynamics, which allows manipulating the property dictionary at runtime, means that you can now effectively add/remove properties to/from an object at runtime by applying the JsonPatchDocument to it.

It also works for nested objects, arrays and objects in an array.  For example, to add a property Street to an object Address for the second person in an array of people, this should be your patch document:

JsonPatchDocument patchDoc = new JsonPatchDocument();
patchDoc.Add("People/1/Address/Street", "My street");

Happy coding! :)

 Tweet about this on TwitterShare on LinkedInShare on Facebook