2014-12-16 6 views
13

Betrachten dem unten angegebenen BeispielprogrammModify existierendes Objekt mit neuem Teil JSON Daten mit Json.NET

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

Das Ergebnis der Patch() Verfahren soll von patch zu calendar außer wie geändert gleich sein. Das bedeutet; Id wäre unverändert, CoffeeProvider wäre null und Meetings würde einen einzelnen Artikel in Room3 enthalten.

  1. Wie kann man eine allgemeine Patch() Methode erstellen, die für jedes Objekt (nicht nur das Beispiel Kalender Objekt) deserializable von Json.NET funktionieren wird?

  2. Wenn (1) dies nicht durchführbar ist, welche Beschränkungen wären damit möglich und wie würde es umgesetzt?

+1

Vielleicht habe ich die Frage missverstanden. Möchten Sie Ihr Objekt ändern oder es klonen und den Klon ändern? – dbc

+0

Ändern funktioniert tatsächlich am besten in meinem Szenario. Wenn es jedoch eine eingebaute Funktionalität zum Klonen gibt, würde es mir nichts ausmachen, dies auch zu tun. Wenn keine eingebaute Funktionalität vorhanden ist, könnte ich das Objekt einfach tiefklonen (zum Beispiel durch Serialisierung + Deserialisierung), bevor ich es patche. – Linus

+1

Deep-Cloning über Json.Net ist, was ich vorschlagen würde. Aktualisierte Antwort mit einem Prototyp. – dbc

Antwort

15

Sie wollen JsonSerializer.Populate() oder seine statische Wrappermethode JsonConvert.PopulateObject():

Füllt die JSON-Werte auf das Zielobjekt.

Zum Beispiel, hier ist es eine Instanz Ihrer Calendar Klasse Aktualisierung:

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

Und das erzeugte Debug-Ausgabe ist:

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

aktualisieren

Wenn Sie möchte zuerst kopieren, könnten Sie tun:

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