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

Posted

技术标签:

【中文标题】使用 Json.NET 使用新的部分 JSON 数据修改现有对象【英文标题】:Modify existing object with new partial JSON data using Json.NET 【发布时间】:2015-02-15 04:19:10 【问题描述】:

考虑下面的示例程序

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 中的单个项目。

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

    如果 (1) 这不可行,有哪些限制可以使其可行以及如何实施?

【问题讨论】:

也许我误解了这个问题。你想修改你的对象,还是克隆它并修改克隆? 修改实际上在我的场景中效果最好。但是,如果有内置的克隆功能,我也不介意知道如何做到这一点。如果没有内置功能,我可以在修补之前深度克隆对象(例如通过序列化+反序列化)。 通过 Json.Net 进行深度克隆是我的建议。用原型更新了答案。 【参考方案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>(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;
    

【讨论】:

以上是关于使用 Json.NET 使用新的部分 JSON 数据修改现有对象的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 LINQ 的 JSON.NET 计算我的 JSON 文件中的子项数

使用 System.Text.Json 反序列化匿名类型

使用json.net做uwp开发时,怎样判断一个json字符串中的某个数组成员是不是为空?(c#)

.NET Core手记 - Json.NET的使用

C#JSON.Net将项目放在另一个列表中

Json.NET 用最少的小数位序列化浮点/双精度,即没有多余的“.0”?