How can I create a JsonPatchDocument to compare two C # objects?

Since I have two c # objects of the same type, I want to compare them to create a JsonPatchDocument.

I have a StyleDetail class defined as follows:

public class StyleDetail { public string Id { get; set; } public string Code { get; set; } public string Name { get; set; } public decimal OriginalPrice { get; set; } public decimal Price { get; set; } public string Notes { get; set; } public string ImageUrl { get; set; } public bool Wishlist { get; set; } public List<string> Attributes { get; set; } public ColourList Colours { get; set; } public SizeList Sizes { get; set; } public ResultPage<Style> Related { get; set; } public ResultPage<Style> Similar { get; set; } public List<Promotion> Promotions { get; set; } public int StoreStock { get; set; } public StyleDetail() { Attributes = new List<string>(); Colours = new ColourList(); Sizes = new SizeList(); Promotions = new List<Promotion>(); } } 

if I have two StyleDetail objects

 StyleDetail styleNew = db.GetStyle(123); StyleDetail styleOld = db.GetStyle(456); 

Now I want to create a JsonPatchDocument so that I can post the differences to my REST API ... How to do this?

 JsonPatchDocument patch = new JsonPatchDocument(); // Now I want to populate patch with the differences between styleNew and styleOld - how? 

javascript has a library for this https://www.npmjs.com/package/rfc6902

Calculate the difference between two objects:

rfc6902.createPatch ({first: 'Chris'}, {first: 'Chris', last: 'Brown'});

 [ { op: 'add', path: '/last', value: 'Brown' } ] 

but I'm looking for a C # implementation

+17
source share
4 answers

Let me misuse the fact that your classes are serializable in JSON! Here is the first attempt by the patch creator, who does not care about your real object, only about the JSON representation of this 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); } } } } 

Using:

 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" } ] 
+12
source

You can use my DiffAnalyzer. It is based on reflection, and you can adjust the depth that you want to analyze.

https://github.com/rcarubbi/Carubbi.DiffAnalyzer

 var before = new User { Id = 1, Name="foo"}; var after= new User { Id = 2, Name="bar"}; var analyzer = new DiffAnalyzer(); var results = analyzer.Compare(before, after); 
0
source

The employee referred to this blog post: https://www.janaks.com.np/implementing-jsonpatch-in-aspnet-core/ , which has an example that creates a JsonPatchDocument object:

 //Creating JsonPatchDocument //Result: [{"op":"replace", "path":"/review", "value":"Good Speaker. I like presentation Style."}] var jsonPatch = new JsonPatchDocument<SpeakerReview>().Replace(x => x.Review, "Good Speaker. I like presentation Style."); //In your application get speaker review object from database base on review Id var speakerFromDb = new SpeakerReview { ReviewId = 2, SpeakerId = 101, Rate = 2.5M, Review = "Good speaker.", ReviewDate = DateTime.UtcNow.AddDays(-1) }; //Apply changes to speaker object jsonPatch.ApplyTo(speakerFromDb); //update speaker in database and return updated object return Ok(speakerFromDb); 
-2
source

You can use this

You can install using NuGet, see SimpleHelpers.ObjectDiffPatch on NuGet.org

 PM> Install-Package SimpleHelpers.ObjectDiffPatch 

Using:

 StyleDetail styleNew = new StyleDetail() { Id = "12", Code = "first" }; StyleDetail styleOld = new StyleDetail() { Id = "23", Code = "second" }; var diff = ObjectDiffPatch.GenerateDiff (styleOld , styleNew ); // original properties values Console.WriteLine (diff.OldValues.ToString()); // updated properties values Console.WriteLine (diff.NewValues.ToString()); 
-3
source

Source: https://habr.com/ru/post/1267308/


All Articles