考虑下面的示例程序
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设置为null并Meetings包含位于Room3中的单个项目。
Patch()
calendar
patch
Id
CoffeeProvider
null
Meetings
如何创建一种通用Patch()方法,该方法适用于Json.NET可反序列化的任何对象(不仅是示例Calendar对象)?
如果(1)这不可行,将有哪些限制使其可行以及将如何实施?
您想要JsonSerializer.Populate()它的静态包装器方法JsonConvert.PopulateObject():
JsonSerializer.Populate()
JsonConvert.PopulateObject()
将JSON值填充到目标对象上。
例如,这里正在更新您的Calendar类的实例:
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>(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>(T obj, string patch) { var serializer = new JsonSerializer(); var json = JsonConvert.SerializeObject(obj); var copy = JsonConvert.DeserializeObject<T>(json); using (var reader = new StringReader(patch)) { serializer.Populate(reader, copy); } return copy; }