2016-06-15 6 views
5

Mit Json.net (Newtonsoft.json), wie kann ich eine C# -Klasse (oder Klassen) definieren, um die JSON unten zu behandeln?JSON zu C# - listet Felder ohne Unterfeldnamen in JSON auf?

Das Feld "Daten" scheint eine Liste der Unterfelder der Ebene/Beschreibung zu sein, aber beachten Sie, dass sie nicht mit vorangestellten Feldnamen sind.

Das Feld "Fehler" scheint eine Liste von Fehlernummern/Fehlermeldungen zu sein, aber beachten Sie, dass auch sie nicht mit vorangestellten Feldnamen sind.

Diese Klassendefinition generiert keine Parsing-Fehler; Der Inhalt von Daten und Fehlern ist jedoch nicht korrekt.

public class ApiResponse 
{ 
    [JsonProperty(PropertyName = "status")] 
    public string Status; 

    [JsonProperty(PropertyName = "data")] 
    public IEnumerable<KeyValuePair<string, string>> Data; 

    [JsonProperty(PropertyName = "error")] 
    public IEnumerable<KeyValuePair<int, string>> Errors; 
}; 

// this doesn't throw a parsing exception, but the resulting 
// Data and Errors fields are not correctly populated. 
var x = JsonConvert.DeserializeObject<ApiResponse>(SampleJson); 

Jede Hilfe wäre dankbar, danke.

+0

Dies könnte Ihnen helfen: http://stackoverflow.com/questions/27744199/converting-array-to-ienumerablet –

Antwort

4

Versuchen Sie, Ihre Mitglieder Data und Errors als IEnumerables von Wörterbüchern anstelle von IEnumerables von KeyValuePairs zu definieren. (Json.Net erwartet KeyValuePairs in JSON als Objekte mit expliziten Key und Value Eigenschaften dargestellt werden, was nicht ist, was Sie da haben.)

public class ApiResponse 
{ 
    [JsonProperty(PropertyName = "status")] 
    public string Status; 

    [JsonProperty(PropertyName = "data")] 
    public IEnumerable<Dictionary<string, string>> Data; 

    [JsonProperty(PropertyName = "error")] 
    public IEnumerable<Dictionary<int, string>> Errors; 
}; 

Sie dann die Daten aus mit einem foreach Schleife mit SelectMany lesen kann:

var x = JsonConvert.DeserializeObject<ApiResponse>(SampleJson); 
foreach (var kvp in x.Data.SelectMany(d => d)) 
{ 
    Console.WriteLine(kvp.Key + ": " + kvp.Value); 
} 
foreach (var kvp in x.Errors.SelectMany(d => d)) 
{ 
    Console.WriteLine(kvp.Key + ": " + kvp.Value); 
} 

Fiddle: https://dotnetfiddle.net/KJuAPu

+0

Die Verwendung von Dictionary <> funktioniert besser als KeyValuePair. Mein Problem mit der Verwendung von Dictionary ist, dass das Datenfeld erscheint, als könnte es mehrere "Warnungen" haben. Das Fehlerfeld scheint gut zu passen, da ich annehme, dass die Fehlernummer nur einmal angezeigt wird. – Tony

+0

Es wird immer noch mit dieser Struktur arbeiten. Mit 'SelectMany' können Sie alles abrufen, unabhängig davon, wie viele Wörterbücher in jedem Array enthalten sind oder wie viele Einträge in jedem Wörterbuch vorhanden sind. Geige: https://dotnetfiddle.net/mLZBec –

+0

Ich sehe das jetzt. Ich dachte, es wäre nur ein Wörterbuch. Es ist nicht, es ist ein IEnumerable >. Im Grunde eine Liste von Einzelwort-Wörterbüchern. Vielen Dank. – Tony

-1

Es gibt einige Probleme mit der Klasse, die Sie erstellt haben. Wie in der JSON-Spezifikation angegeben, sollten Sie Ihre Klassen ähnlich wie im folgenden Code erstellen.

public class Data 
    { 
     [JsonProperty(PropertyName = "warning")] 
     public string Warning { get; set; } 
    } 
    public class Error 
    { 
     [JsonProperty(PropertyName = "373")] 
     public string Col_373 { get; set; } 
    } 

    public class ApiResponse 
    { 
     [JsonProperty(PropertyName = "status")] 
     public string Status { get; set; } 
     [JsonProperty(PropertyName = "data")] 
     public List<Data> Data { get; set; } 
     [JsonProperty(PropertyName = "error")] 
     public List<Error> Error { get; set; } 
    } 

Nachdem Sie die Struktur wie folgt entworfen haben, können Sie es jederzeit auf Ihre Objektstruktur wie folgende Code-Schnipsel zurück. Es scheint, dass Sie mit den Namen und Werten der Property verwechselt werden.

string json = "{\"status\":\"error\", \"data\": [{\"warning\" : \"your input was wrong\" }], \"error\": [{\"373\": \"Error description goes here\"}]}"; 

var res = JsonConvert.DeserializeObject<ApiResponse>(json); 

Eine weitere Beobachtung.

"373": "Fehlerbeschreibung geht hier"

Bitte verwenden Sie keine Nummer als Schlüssel/Spaltennamen.

+0

Ich bin mir nicht sicher, ob das OP die Kontrolle über den JSON hat - das ist wahrscheinlich eine API eines Drittanbieters. Wenn dies der Fall ist, wird Ihre Lösung nicht funktionieren, wenn der Fehlercode etwas anderes als "373" ist oder die Daten etwas anderes als "Warnung" sind. Sie benötigen etwas, das mit variablen Schlüsselnamen umgehen kann. –

+0

@BrianRogers Sie sind richtig, ich kontrolliere nicht den JSON. – Tony

+0

@Tony Schauen Sie sich meine Antwort dann an; Es sollte mit Ihrem JSON funktionieren und variable Schlüsselnamen verarbeiten können. –