Как я могу создать JsonPatchDocument для сравнения двух объектов С#?
Поскольку у меня есть два объекта c # одного типа, я хочу сравнить их, чтобы создать JsonPatchDocument.
У меня есть класс StyleDetail, определенный следующим образом:
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>();
}
}
если у меня есть два объекта StyleDetail
StyleDetail styleNew = db.GetStyle(123);
StyleDetail styleOld = db.GetStyle(456);
Теперь я хочу создать JsonPatchDocument, чтобы можно было отправлять различия в мой REST API... Как это сделать?
JsonPatchDocument patch = new JsonPatchDocument();
// Now I want to populate patch with the differences between styleNew and styleOld - how?
в javascript есть библиотека для этого https://www.npmjs.com/package/rfc6902
Рассчитать разницу между двумя объектами:
rfc6902.createPatch({first: 'Chris'}, {first: 'Chris', last:
'Brown'});
[ { op: 'add', path: '/last', value: 'Brown' } ]
но я ищу реализацию С#
Ответы
Ответ 1
Позвольте злоупотреблять тем фактом, что ваши классы сериализуемы в JSON!
Вот первая попытка создателя патча, который не заботится о вашем реальном объекте, только о JSON-представлении этого объекта.
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);
}
}
}
}
Использование:
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"
}
]
Ответ 2
Вы можете использовать мой DiffAnalyzer. Он основан на отражении, и вы можете настроить глубину, которую вы хотите проанализировать.
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);
Ответ 3
Сотрудник сослался на это сообщение в блоге: https://www.janaks.com.np/implementing-jsonpatch-in-aspnet-core/, в котором есть пример, который создает объект JsonPatchDocument:
//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);
Ответ 4
Вы можете использовать этот
Вы можете установить с помощью NuGet, см. SimpleHelpers.ObjectDiffPatch на NuGet.org
PM> Install-Package SimpleHelpers.ObjectDiffPatch
Использование:
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());