How can I create a JsonPatchDocument from comparing two c# objects?

Let's abuse the fact that your classes are serializable to JSON! Here's a first attempt at a patch creator that doesn't care about your actual object, only about the JSON representation of that object.

public static JsonPatchDocument CreatePatch(object originalObject, object modifiedObject)
{
    var original = JObject.FromObject(originalObject);
    var modified = JObject.FromObject(modifiedObject);

    var patch = new JsonPatchDocument();
    FillPatchForObject(original, modified, patch, "/");

    return patch;
}

static void FillPatchForObject(JObject orig, JObject mod, JsonPatchDocument patch, string path)
{
    var origNames = orig.Properties().Select(x => x.Name).ToArray();
    var modNames = mod.Properties().Select(x => x.Name).ToArray();

    // Names removed in modified
    foreach (var k in origNames.Except(modNames))
    {
        var prop = orig.Property(k);
        patch.Remove(path + prop.Name);
    }

    // Names added in modified
    foreach (var k in modNames.Except(origNames))
    {
        var prop = mod.Property(k);
        patch.Add(path + prop.Name, prop.Value);
    }

    // Present in both
    foreach (var k in origNames.Intersect(modNames))
    {
        var origProp = orig.Property(k);
        var modProp = mod.Property(k);

        if (origProp.Value.Type != modProp.Value.Type)
        {
            patch.Replace(path + modProp.Name, modProp.Value);
        }
        else if (!string.Equals(
                        origProp.Value.ToString(Newtonsoft.Json.Formatting.None),
                        modProp.Value.ToString(Newtonsoft.Json.Formatting.None)))
        {
            if (origProp.Value.Type == JTokenType.Object)
            {
                // Recurse into objects
                FillPatchForObject(origProp.Value as JObject, modProp.Value as JObject, patch, path + modProp.Name +"/");
            }
            else
            {
                // Replace values directly
                patch.Replace(path + modProp.Name, modProp.Value);
            }
        }       
    }
}

Usage:

var patch = CreatePatch(
    new { Unchanged = new[] { 1, 2, 3, 4, 5 }, Changed = "1", Removed = "1" },
    new { Unchanged = new[] { 1, 2, 3, 4, 5 }, Changed = "2", Added = new { x = "1" } });

// Result of JsonConvert.SerializeObject(patch)
[
  {
    "path": "/Removed",
    "op": "remove"
  },
  {
    "value": {
      "x": "1"
    },
    "path": "/Added",
    "op": "add"
  },
  {
    "value": "2",
    "path": "/Changed",
    "op": "replace"
  }
]

Tags:

C#

Json Patch