2013-12-12 17 views
5

Ich verwende C#, um eine Sammlung von JSON-Zeichenfolgen zu deserialisieren. Jede Zeichenfolge hat eine Eigenschaft employer_normalized, die eine string und List<int> enthält, wobei die Werte in der List immer positiv sind. In einigen Fällen employer_normalized ist auf -1 festgelegt, also möchte ich diese Fälle mit einem Verhalten, das employer_normalized auf null setzt, überschreiben.Deserialisieren von JSON, das eine Ganzzahl oder eine Liste von Zeichenfolgen in C sein könnte

Hier ist meine Klasse:

public class EmployerNormalized 
{ 
    public string company; 
    public List<int> code; 
} 

Gut JSON

"employer_normalized": { 
     "company": "self", 
     "code": [ 
      "4581 ", 
      "6732 ", 
      "9121", 
      "9999 ", 
      "5947 ", 
      "8322 ", 
      "8351 ", 
      "7335 ", 
      "9999 ", 
      "4225 ", 
      "8399 " 
     ] 
     } 

Bad JSON

"employer_normalized": -1 

ich derzeit Json.NET bin mit meinem JSON Parsen zu tun. Was ist eine elegante Lösung zur Lösung dieses Problems? Ist es am besten, den employer_normalized Wert auf null zu setzen, wenn es -1 ist? Wenn ja, wie kann ich das tun?

+2

Feuer wer auch immer die Anwendung entwickelt, die diese JSON erzeugt :) –

+0

Ich wünschte, ich könnte. Ich stehe jedoch vorerst damit fest, also muss ich einen Weg finden, mit diesen spezifischen Fällen umzugehen. – RouteMapper

Antwort

3

Sie können einen benutzerdefinierten JsonConverter verwenden, um mit dieser Situation umzugehen. Wo auch immer Sie eine EmployerNormalized erwarten, der Konverter kann prüfen, ob der Wert dieser Eigenschaft -1 ist und Null zurückgeben, andernfalls deserialize es normalerweise. Hier

ist der Code für den Konverter:

public class EmployerNormalizedConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(EmployerNormalized)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JToken token = JToken.Load(reader); 
     if (token.Type == JTokenType.Object) 
     { 
      return token.ToObject<EmployerNormalized>(); 
     } 
     return null; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Und hier ist eine Demo zeigt, wie man es benutzt:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @" 
     { 
      ""good"" : { 
       ""company"": ""self"", 
       ""code"": [ 
        ""4581 "", 
        ""6732 "", 
        ""9121"", 
        ""9999 "", 
        ""5947 "", 
        ""8322 "", 
        ""8351 "", 
        ""7335 "", 
        ""9999 "", 
        ""4225 "", 
        ""8399 "" 
       ] 
      }, 
      ""bad"" : -1 
     }"; 

     Wrapper wrapper = 
      JsonConvert.DeserializeObject<Wrapper>(json, 
       new EmployerNormalizedConverter()); 

     DumpEmployer("good", wrapper.good); 
     DumpEmployer("bad", wrapper.bad); 
    } 

    private static void DumpEmployer(string prop, EmployerNormalized emp) 
    { 
     Console.WriteLine(prop); 
     if (emp != null) 
     { 
      Console.WriteLine(" company: " + emp.company); 
      Console.WriteLine(" codes: " + 
       string.Join(", ", emp.code.Select(c => c.ToString()))); 
     } 
     else 
      Console.WriteLine(" (null)"); 
    } 

    public class Wrapper 
    { 
     public EmployerNormalized good { get; set; } 
     public EmployerNormalized bad { get; set; } 
    } 

    public class EmployerNormalized 
    { 
     public string company; 
     public List<int> code; 
    } 
} 

Hier ist der Ausgang:

good 
    company: self 
    codes: 4581, 6732, 9121, 9999, 5947, 8322, 8351, 7335, 9999, 4225, 8399 
bad 
    (null) 

Wichtiger Hinweis: Sie könnten versucht sein, diezu dekorieren 0 Klasse mit , aber wenn Sie das tun, dann wird der Konverter, in seiner aktuellen Form, am Ende selbst rekursiv aufrufen, bis es mit einem StackOverflowException Fehler ausgibt. Wenn Sie/brauchen das Attribut verwendet werden sollen, dann wird der Code der ReadJson Methode im Konverter muß geändert werden, damit er manuell eine Instanz der Klasse EmployerNormalized erstellt und füllt alle seine Eigenschaften individuell statt token.ToObject<EmployerNormalized>() aufrufen. Hier ist eine alternative Version von ReadJson, die die Rekursion Problem vermeiden:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    JToken token = JToken.Load(reader); 
    if (token.Type == JTokenType.Object) 
    { 
     EmployerNormalized employer = new EmployerNormalized(); 
     employer.company = token["company"].ToString(); 
     employer.code = token["code"].ToObject<List<int>>(); 
     return employer; 
    } 
    return null; 
} 
+0

Das ist perfekt! Vielen Dank! – RouteMapper

+0

Kein Problem; froh, dass ich Helfen kann. –

+0

Irgendeine Idee, warum ich diesen Fehler bekommen könnte? 'Eine nicht behandelte Ausnahme vom Typ 'System.StackOverflowException' ist in Newtonsoft.Json.dll aufgetreten. Ich habe es mit einer Liste von Objekten zu tun, die ein 'EmployerNormalized' Objekt enthalten. – RouteMapper

1

Ich weiß, das saugt, aber Sie können zunächst versuchen, die JSON string auf einen Object mit der Struktur Ihres Gut JSON, und im Fall eines Parsing-Fehler zu analysieren, analysieren, um den zweiten Fall (Bad JSON).

+0

Also meinst du, ich sollte eine Klasse erstellen, die das fehlerhafte JSON darstellt und im Falle einer Ausnahme das analysieren? – RouteMapper

+0

Ziemlich viel - * peinlich * – everton

+0

Ich denke, die einfachste Lösung ist es, 'employer_normalised' auf' null' zu setzen, aber ich muss das nur notieren, weil ich plane, diese Datensätze in eine Datenbank einzufügen. Meine DB wird schreien, wenn ich einen "Null" -Wert in ein Nicht-Nullable-Feld einfüge. Pfui! – RouteMapper

Verwandte Themen