Giter Site home page Giter Site logo

nancy.jsonpatch's Introduction

Nancy.JsonPatch NuGet Version

Adds JSON Patch functionality to Nancy

Patch["/customer/{customerId}"] = _ =>
{
    Customer customer = _repository.Get(_.customerId);

    if (this.JsonPatch(customer))
        _repository.Save(customer);

    return HttpStatusCode.NoContent;
};

This is an example of a JSON Patch document:

[
  { "op": "test", "path": "/a/b/c", "value": "foo" },
  { "op": "remove", "path": "/a/b/c" },
]

For a good introduction to JSON Patch, checkout jsonpatch.com or RFC6902.

Installation

Install via NuGet:

PM > Install-Package Nancy.JsonPatch

Getting Started

Nancy.JsonPatch adds an extension method to NancyModule, so usage is as simple as calling:

this.JsonPatch(myThing);

from anywhere inside your route action.

Nancy.JsonPatch will then deserialize the request body and apply the patch operations to your object.

RFC6902 states that if one operation in the document fails, the entire document should not be considered successful. In other words, you only want to save the changes to your object if all operations in the document succeed.

The .JsonPatch() extension method returns a JsonPatchResult indicating the result of the patch. This can be implicitly converted to a bool, allowing you to do this:

  if (this.JsonPatch(myThing))
      _repository.Save(myThing);

Advanced Error Handling

RFC5789 describes various error codes that should be returned depending on the result of the JSON Patch operation. If you wish to handle failure in this way, the JsonPatchResult object returned from .JsonPatch() should give you the information you need:

public class JsonPatchResult
{
    // True if the operation succeeds, otherwise false
    public bool Succeeded { get; set; }

    // In the event that an operation fails, this will contain a message describing the failure
    public string Message { get; set; }

    // Can be either:
    //  TestFailed - A 'test' operation failed
    //  CouldNotParseJson - The JSON Patch document in the request body is invalid
    //  CouldNotParsePath - A 'path' could not be mapped to a property on the object being patched
    //  CouldNotParseFrom - As above, but for the 'from' path used for copy/move operations
    //  OperationFailed - An operation in the document could not be completed (see the Message for details)
    public JsonPatchFailureReason FailureReason { get; set; }
}

For example:

var patchResult = this.JsonPatch(myThing);
if (!patchResult)
{
    if (patchResult.FailureReason == JsonPatchFailureReason.CouldNotParsePath)
        return HttpStatusCode.Conflict;
    else
        return HttpStatusCode.UnprocessableEntity;
}

_repository.Save(myThing);
return HttpStatusCode.NoContent;

JSON Patch operations in details

Since C# is strongly typed, our implementation has to be slightly different from that described in RFC6902.

This is how Nancy.JsonPatch implements each JsonPatch operation:

Add

[
  { "op": "add", "path": "/Name", "value": "Nancy" }
]

If the 'path' refers to a specific item in a collection (e.g. '/SomeCollection/2'), the item is added before that item.

If the 'path' uses '-', to refer to the end of the collection (e.g '/SomeCollection/-') the item is added to the end of the existing collection.

We can't add properties to objects in .NET. Therefore if the 'path' refers to a property that is not a collection (e.g. '/FirstName'), Add is treated as Replace.

Remove

[
  { "op": "remove", "path": "/Name" }
]

For collections, removes the item from the collection.

Since we can't remove properties from strongly-typed objects, if the 'path' does not refer to a collection then the target property will be set to it's default value (e.g. null for reference types)

Replace

[
  { "op": "replace", "path": "/SomeCollection/1", "value": { "FirstName" : "Nancy"  } }
]

Replaces the property referred to by the 'path' with the new 'value'.

Copy

[
  { "op": "copy", "path": "/Customer/1", "from": "/TopCustomer" }
]

Copies the value of one property to another.

Performs an add operation, taking the value of the item in the 'from' path and adding to the object in referred to by 'path'.

Move

[
  { "op": "move", "path": "/Customer/1", "from": "/TopCustomer" }
]

Moves the value of one property to another.

The same as copy, but performs a remove operation on the original 'path' first.

Test

[
  { "op": "test", "path": "/Customer/1/FirstName", "value": "Nancy" }
]

Tests that the value of the property referred to by the 'path' matches that specified in 'value'. If the test fails, execution of the JSON Patch document stops and an error is returned from the .JsonPatch() method.

So is this fine to use right now?

Yeah! If you do find any issues though, please let me know (or, even better, submit a pull request ๐Ÿ˜„ ).

nancy.jsonpatch's People

Contributors

dsaunders avatar mrstebo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

nancy.jsonpatch's Issues

Use with JsonSerializer

I am using a JsonSerializer to convert my models property names in to snake case. But if I try and do any of the operations using the snake-cased format it says it cannot find the path.

I will try and get a PR ready for adding in this feature.

Json.Net for deserialization

Hi,

Firstly, thanks for implementing patch operations! It's exactly what I need for what I'm doing.

One question: is there a way I can easily substitute in json.net instead of JavaScriptSerializer? Or do you know if someone has forked and made that change or is working on it?

Thanks,

-John

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.