fredag, januar 04, 2013

JSON-Patch support in Ramone

Ramone (my C# web API and REST client) now supports JSON patch documents as defined in http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-08. This is yet a draft standard so Ramone's implementation may need some tweaking later on to work.

A patch document represents a set of changes to a JSON resource. This can be “add” new value, “remove” value or other similar operations.

In Ramone we use the class JsonPatchDocument to build a patch document. For instance like this:

JsonPatchDocument patch = new JsonPatchDocument<myresourcetype>();

// Supply path as a string
patch.Replace("/Title", "My new title");

// Supply path as a typed referenc
patch.Replace(d => d.Title, "Another title");

The above example corresponds to this json-patch document (which you can get by calling ToString() or Write() on the patch variable):

[
  { op: "replace", path: "/Title", value: "My new title" },
  { op: "replace", path: "/Title", value: "Another title" }
]

The use of lambdas like d => d.Title is a simple and type safe way to supply a patch path with respect to a given resource class. Using lambdas like this ensure paths are updated when refactoring variable names in Visual Studio.

Patch documents can be sent to a server like this:

JsonPatchDocument patch = ... build patch document ...

Request request = Session.Bind(ResourceUrl);

using (var response = request.Patch(patch))
{
  ... do stuff with response ...
}

Ramone also supports reading and applying patch documents (using the “visitor” pattern). You do although have to implement the actual operations yourself—Ramone cannot do that for you. Here is one example:

using (TextReader r = ... get reader from some JSON input ...)
{
  // Read patch document from input
  JsonPatchDocument patch = JsonPatchDocument.Read(r);

  // Create instance of patching logic
  MyPatchVisitor visitor = new MyPatchVisitor();

  // Apply patch document
  patch.Apply(visitor);
}


// Implements "visitor" pattern where each patch operation in 
// the patch document will be translated to a call to Add(...),
// Replace(...) and so on.
class MyPatchVisitor : JsonPatchDocumentVisitor
{
  public override void Add(string path, object value)
  {
    ... implement "add" logic for target data ...
  }
}

There is also an optional typed version of the JsonPatchDocumentVisitor which will simplify your operations slightly:

class MyTypedPatchVisitor : JsonPatchDocumentVisitor<myresourcetype>
{
  public override void Add(string path, object value)
  {
    // Test path against delegate and cast value to int if
    // they match. Then execute the action delegate.
    IfMatch<int>(r => r.Id, path, value,
      v => ... do stuff with integer "v"...);
  }
}

4 kommentarer:

  1. Do you have a complete example on how we can use it in our .NET code? I have just added ramone class using nuget but I dont know how to use it. I searched for a working example but couldn't find one. Can you help? If you have an example handy, that will really help. Thanks in advance.

    shamrez.ahmed@gmail.com

    SvarSlet
    Svar
    1. Sorry, no I don't have any better example than those above (which are fairly complete). There is also a few test cases here: https://github.com/JornWildt/Ramone/blob/master/Ramone.Tests/MediaTypes/JsonPatch/JsonPatchTests.cs

      Slet
  2. Denne kommentar er fjernet af forfatteren.

    SvarSlet
  3. Thanks Jorn! I am further exploring your library and trying to make it work. I will let you know if I have more questions but it seems yours is the only C# library at this time that supports json-patch operations. I have tried RestSharp's restclient and that is not working. It throws "unsupported_media_type" error when I pass "application/json-patch+json" in the header. I am hoping your library will work and I am keeping my fingers crossed otherwise I will have to write my own RestClient and that's something I dont want to do (because of shortage of time). Thanks again for taking the time to respond. I really appreciate it! And you have done an EXCELLENT job! Fantastic!!!

    SvarSlet