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

标签 c# json json.net json-deserialization

考虑下面的示例程序

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

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

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

最佳答案

你想要JsonSerializer.Populate()或其静态包装方法 JsonConvert.PopulateObject() :

Populates the JSON values onto the target object.

例如,这里它正在更新您的 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;
    }

关于c# - 使用 Json.NET 使用新的部分 JSON 数据修改现有对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27511675/

相关文章:

c# - 使用 ScriptManager.RegisterClientScriptIninclude 注册 JavaScript 文件

java - JSONArray 为空

c# - Json.Net - 序列化不带引号的属性名称

c# - System.Text.Json 序列化 Unicode 字符(如表情符号)的问题

c# - JSON反序列化可变数量的属性

c# - 如何使用反射返回从泛型子类化的所有类,而不给出特定的泛型类型

c# - 如何将日期时间变量设置为空

c# - WPF模糊文本框中的文本

c# - 在 C# restful web 服务中删除 xml 命名空间返回字符串

javascript - 可以将项目添加到队列的后面,旧的项目可以从队列的前面删除