使用Json.NET使用新的部分JSON数据修改现有对象

考虑下面的示例程序

var calendar = new Calendar { Id = 42, CoffeeProvider = "Espresso2000", Meetings = new[] { new Meeting { Location = "Room1", From = DateTimeOffset.Parse("2014-01-01T00:00:00Z"), To = DateTimeOffset.Parse("2014-01-01T01:00:00Z") }, new Meeting { Location = "Room2", From = DateTimeOffset.Parse("2014-01-01T02:00:00Z"), To = DateTimeOffset.Parse("2014-01-01T03:00:00Z") }, } }; var patch = @"{ 'coffeeprovider': null, 'meetings': [ { 'location': 'Room3', 'from': '2014-01-01T04:00:00Z', 'to': '2014-01-01T05:00:00Z' } ] }"; var patchedCalendar = Patch(calendar, patch); 

Patch()方法的结果应该等于calendar除非由patch更改。 这意味着; Id将保持不变, CoffeeProvider将设置为nullMeetings将包含位于Room3中的单个项目。

  1. 如何创建一个通用的Patch()方法,该方法适用于Json.NET可反序列化的任何对象(不仅仅是示例Calendar对象)?

  2. 如果(1)这是不可行的,会有什么限制使其可行以及如何实施?

您需要JsonSerializer.Populate()或其静态包装器方法JsonConvert.PopulateObject()

将JSON值填充到目标对象上。

例如,这里是更新Calendar类的实例:

 public static class TestPopulate { public static void Test() { var calendar = new Calendar { Id = 42, CoffeeProvider = "Espresso2000", Meetings = new[] { new Meeting { Location = "Room1", From = DateTimeOffset.Parse("2014-01-01T00:00:00Z"), To = DateTimeOffset.Parse("2014-01-01T01:00:00Z") }, new Meeting { Location = "Room2", From = DateTimeOffset.Parse("2014-01-01T02:00:00Z"), To = DateTimeOffset.Parse("2014-01-01T03:00:00Z") }, } }; var patch = @"{ 'coffeeprovider': null, 'meetings': [ { 'location': 'Room3', 'from': '2014-01-01T04:00:00Z', 'to': '2014-01-01T05:00:00Z' } ] }"; Patch(calendar, patch); Debug.WriteLine(JsonConvert.SerializeObject(calendar, Formatting.Indented)); } public static void Patch(T obj, string patch) { var serializer = new JsonSerializer(); using (var reader = new StringReader(patch)) { serializer.Populate(reader, obj); } } } 

并且产生的调试输出是:

 { "id": 42, "coffeeprovider": null, "meetings": [ { "location": "Room3", "from": "2014-01-01T04:00:00+00:00", "to": "2014-01-01T05:00:00+00:00" } ] } 

更新

如果你想先复制,你可以这样做:

  public static T CopyPatch(T obj, string patch) { var serializer = new JsonSerializer(); var json = JsonConvert.SerializeObject(obj); var copy = JsonConvert.DeserializeObject(json); using (var reader = new StringReader(patch)) { serializer.Populate(reader, copy); } return copy; }