Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Consider the below example program

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);

The result of the Patch() method should be equal to calendar except as changed by patch. That means; Id would be unchanged, CoffeeProvider would be set to null and Meetings would contain a single item located in Room3.

  1. How does one create a general Patch() method that will work for any object (not just the example Calendar object) deserializable by Json.NET?

  2. If (1) this is not feasible, what would be some restrictions that would make it feasible and how would it be implemented?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
167 views
Welcome To Ask or Share your Answers For Others

1 Answer

You want JsonSerializer.Populate() or its static wrapper method JsonConvert.PopulateObject():

Populates the JSON values onto the target object.

For instance, here it is updating an instance of your Calendar class:

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);
        }
    }
}

And the debug output produced is:

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

Update

If you want to copy first, you could do:

    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;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...