2016-05-21 18 views
0

Ich versuche ein Werkzeug zu erstellen, das JSON-Objekte mit einigen C# -POCO-Objekten vergleicht, die ich habe. Dieses Tool hilft mir zu erkennen, wenn neue Felder hinzugefügt oder alte im Vergleich zu meinen Objekten entfernt werden.Ermitteln von Eigenschaften, die nicht in JSON sind, beim Deserialisieren mit Json.Net

Der Fall "neues Feld" ist einfach. Im SerializerSettings setze ich die Eigenschaft MissingMemberHandling auf Error und füge einen Listener zum Error Ereignis hinzu. Wenn ein C# -Feld fehlt, wird das Ereignis mit Details aufgerufen.

Die "alte Feld" -Fall (wo ein C# -Feld/-Eigenschaft nicht festgelegt ist) scheint schwieriger zu lösen. Siehe den folgenden Beispielcode. Dieser Code wird ohne Probleme ausgeführt und erkennt Fälle, wenn ein neues JSON-Feld angezeigt wird, erkennt jedoch nicht, wenn Field2 nicht im JSON enthalten ist.

class TestObject 
{ 
    public int Field1 { get; set; } 

    public int Field2 { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string exampleJson = @"{ ""Field1"": 1 }"; 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.MissingMemberHandling = MissingMemberHandling.Error; 
     settings.Error = Error; 

     try 
     { 
      TestObject obj = JsonConvert.DeserializeObject<TestObject>(exampleJson, settings); 

      Console.WriteLine("Object had no errors"); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Object had errors"); 
     } 
    } 

    private static void Error(object sender, ErrorEventArgs errorEventArgs) 
    { 
     Console.WriteLine(errorEventArgs.ErrorContext.Path + " had " + errorEventArgs.ErrorContext.Error.Message); 
    } 
} 

Ich habe versucht Vertrag Auflöser Umsetzung (und Einstellungen Rückrufe für Deserialisieren), aber sie nicht für jedes Feld (nur für jeden Typ) ...

Schließlich aufgerufen. Ich kann keine [DataMember(IsRequired = true)] oder [JsonProperty(Required = Required.Always)] Attribute hinzufügen.

Antwort

0

Ich könnte eine praktikable Lösung haben.

Durch Erstellen einer ContractResolver kann ich alle Eigenschaften zur Laufzeit auf Required setzen. Dies wird einen Fehler geben, ohne mein Modell zu ändern, aber es gibt nur den ersten Fehler ... es sei denn, Sie Handled zu true im Error Rückruf gesetzt:

class TestObject 
{ 

    public int Field1 { get; set; } 

    public int Field2 { get; set; } 

    public int Field3 { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string exampleJson = @"{ ""Field1"": 1, ""Field4"": 1 }"; 

     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.MissingMemberHandling = MissingMemberHandling.Error; 
     settings.ContractResolver = new ContractResolver(); 
     settings.Error = Error; 

     try 
     { 
      TestObject obj = JsonConvert.DeserializeObject<TestObject>(exampleJson, settings); 

      Console.WriteLine("Object had no errors"); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Object had errors"); 
     } 
    } 

    private static void Error(object sender, ErrorEventArgs errorEventArgs) 
    { 
     errorEventArgs.ErrorContext.Handled = true; 
     Console.WriteLine(errorEventArgs.ErrorContext.Path + " had " + errorEventArgs.ErrorContext.Error.Message); 
    } 
} 

internal class ContractResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty res = base.CreateProperty(member, memberSerialization); 

     res.Required = Required.AllowNull; 

     return res; 
    } 
} 
Verwandte Themen