2016-06-15 16 views
5

Utilizzando Json.net (Newtonsoft.json), come posso definire una classe (o classi) C# per gestire il json qui sotto?JSON a C# - elenca i campi senza nomi di sottocampo in json?

Il campo "dati" sembra essere un elenco di sottocampi di livello/descrizione ma si noti che sono non preceduti dai nomi dei campi.

Il campo "errore" sembra essere un elenco di campi secondari errore-numero/errore-messaggio, ma si noti che anch'essi sono non preceduti dai nomi dei campi.

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

Questa definizione di classe non genera errori di analisi; tuttavia il contenuto di Dati ed errori non è corretto.

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

Qualsiasi aiuto sarebbe apprezzato, grazie.

+0

Questo potrebbe aiutarvi: http://stackoverflow.com/questions/27744199/converting-array-to-ienumerablet –

risposta

4

Provare a definire i membri Data e Errors come IEnumerables di Dizionari piuttosto che IEnumerables di KeyValuePairs. (Json.Net aspetta KeyValuePairs di essere rappresentati in JSON come oggetti con espliciti Key e Value proprietà, che non è quello che hai lì.)

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

È quindi possibile leggere i dati utilizzando un ciclo foreach con SelectMany:

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

Passare a usare Dizionario <> funziona meglio di KeyValuePair. La mia preoccupazione per l'uso del dizionario è che il campo Dati appare come se potesse avere più "avvertimenti". Il campo degli errori sembra essere una buona scelta dato che presumo che il numero di errore venga visualizzato solo una volta. – Tony

+0

Funzionerà ancora con questa struttura. L'utilizzo di 'SelectMany' ti consentirà di ottenere tutto indipendentemente dal numero di dizionari presenti in ciascun array o dal numero di voci presenti in ciascun dizionario. Fiddle: https://dotnetfiddle.net/mLZBec –

+0

Lo vedo ora. Stavo pensando che fosse solo un dizionario. Non lo è, è un IEnumerable >. Fondamentalmente un elenco di dizionari di singola voce. Grazie. – Tony

-1

Ci sono pochi problemi con la classe che hai creato. Come per fornire JSON, dovresti creare le tue classi come il seguente codice.

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

Una volta che avete progettato la struttura come questa, si può sempre tornare indietro alla vostra struttura oggetto come codice seguente snippet. Sembra che tu ti stia confondendo con i nomi e i valori delle proprietà.

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

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

Un'altra osservazione.

"373": "Descrizione errore va qui"

Si prega di non utilizzare il numero come il nome della chiave/colonna.

+0

Non sono sicuro che l'OP abbia il controllo su JSON-- questa è probabilmente un'API di terze parti. Stando così le cose, la tua soluzione non funzionerà se il codice di errore è qualcosa di diverso da "373", oppure i dati sono qualcosa di diverso da "warning". Hai bisogno di qualcosa in grado di gestire i nomi delle chiavi variabili. –

+0

@BrianRogers sei corretto, non controllo il JSON. – Tony

+0

@Tony Dai un'occhiata alla mia risposta allora; dovrebbe funzionare con il tuo JSON e può gestire nomi di chiavi variabili. –

Problemi correlati