2012-01-05 29 views
17

Sto tentando di deserializzare alcuni dati JSON in oggetti per un'applicazione. Fino ad ora è andato tutto bene perché le proprietà sui dati JSON erano statiche (chiave con un valore). Ora ho un risultato in cui la chiave è un dato dinamico.Deserializzazione JSON utilizzando JSon.NET con dati dinamici

Ecco un esempio JSON url:

http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info

La risultante JSON per questo è:

{ "query" : { "pages" : { "6695" : { "counter" : "", 
      "lastrevid" : 468683764, 
      "length" : 8899, 
      "ns" : 0, 
      "pageid" : 6695, 
      "title" : "Citadel", 
      "touched" : "2012-01-03T19:16:16Z" 
     } } } } 

Okay, questo è ottimo, tranne che non posso deserializzare le "pagine" di dati in un oggetto. Se dovessi definire una classe per le pagine che avrebbe dovuto assomigliare a questo:

public class 6695 
{ 
    public string counter { get; set; } 
    public int lastrevid { get; set; } 
    public int length { get; set; } 
    public int ns { get; set; } 
    public int pageid { get; set; } 
    public string title { get; set; } 
    public string touched { get; set; } 
} 

Per deserialze i contenuti (utilizzando JsonConvert.Deserialize (jsondata)) e tutti sappiamo che non possiamo avere una classe chiamata 6695. Non solo, il nome della classe dovrebbe essere diverso (ad esempio pageid = 7145 dovrebbe essere la classe 7145).

Posso sembrare strappare alcuni valori se utilizzo qualcosa come JObject.Parse (contenuto) e quindi accedere agli elementi come JArray ma è piuttosto brutto e sono ancora bloccato nel tentativo di estrarre i dati dall'array delle pagine .

Alla ricerca di qualcuno per aiutare con questo. Non penso che sia raro, non sono solo i dati JSON che ho incontrato prima e non sono sicuro di come gestirlo.

Grazie!

PS dimenticato di menzionare questo è su Windows Phone 7 così "dinamico" non è disponibile!

+0

Non sarebbe il 6695, solo essere nome della proprietà, piuttosto che un nome di classe? Ancora un problema, ma forse puoi fare ricerca e sostituzione della proprietà numerica in un nome fisso. Non sono sicuro di come Json.NET gestisca ciò ma forse puoi provare a deserializzare come dizionario di un tipo di oggetto specifico? –

+0

Probabilmente sono un po 'in ritardo per questa festa, ma la libreria newtonsoft ha JObject per questo ... var obj = JObject.Parse (jsonString); fondamentalmente tratta i dati come un complesso dizionario annidato simile a come si comporta JavaScript nel browser. Si ottiene un'istanza di un "JObject" che consente di accedere a tutto utilizzando la sintassi dell'array, ad esempio: var page = obj ["pages"] ["6695"] – War

risposta

18

Ecco come si utilizza https://github.com/facebook-csharp-sdk/simple-json (https://nuget.org/packages/SimpleJson).

var text = "{\"query\":{\"pages\":{\"6695\":{\"pageid\":6695,\"ns\":0,\"title\":\"Citadel\",\"touched\":\"2012-01-03T19:16:16Z\",\"lastrevid\":468683764,\"counter\":\"\",\"length\":8899}}}}"; 

(con Dynamic)

dynamic json = SimpleJson.DeserializeObject(text); 
string title = json.query.pages["6695"].title; 

foreach (KeyValuePair<string, dynamic> page in json.query.pages) 
{ 
    var id = page.Key; 
    var pageId = page.Value.pageid; 
    var ns = page.Value.ns; 
} 

(utilizzando le classi fortemente tipizzati)

class result 
{ 
    public query query { get; set; } 
} 
class query 
{ 
    public IDictionary<string, page> pages { get; set; } 
} 
class page 
{ 
    public long pageid { get; set; } 
    public string title { get; set; } 
} 

var result = SimpleJson.DeserializeObject<result>(text); 

[Update]

su windows phone cui dinamica non è supportato e non voglio usare classi fortemente tipizzate.

var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(text); 
var query = (IDictionary<string, object>)json["query"]; 
var pages = (IDictionary<string, object>)query["pages"]; 
var pageKeys = pages.Keys; 
var page = (IDictionary<string, object>)pages["6695"]; 
var title = (string)page["title"]; 
+0

Ottimo! Funziona (Json.NET è lo stesso e può usare classi fortemente tipizzate lo stesso era SimpleJson Grazie) – Bil

+0

Mi sono appena imbattuto in questo problema cercando di analizzare i dettagli del file Gist da GitHub. Grazie mille per la risposta qui. Non pensavo di usare IDictionary! –

28

Il metodo più semplice. In questo caso particolare sarebbe probabilmente di andare dynamic.

dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json); 
var lastRevId = data.query.pages["6695"].lastrevid; 

è possibile fare riferimento qualsiasi elemento da esso è [] nome in modo da poter fare qualcosa di simile data["query"]["pages"]["6695"]["lastrevid"]. Ciò otterrà da tutti quei piccoli oggetti in cui il nome non è valido in C#.

+2

Sembra che questo sia per wp7 che non supporta dynamic :(I Lascialo qui per tutti gli altri che non sono vincolati da C# 3 – Buildstarted

+0

Tu ** non è necessario utilizzare il metodo generico **, puoi semplicemente andare come 'dynamic data = JsonConvert.DeserializeObject (json);' –

0

Che ne dici di una semplice ricerca e sostituzione nella stringa JSON? Anche se potrebbe non essere la soluzione più elegante, sarebbe probabilmente la più pragmatica.

+0

Sì, qualcuno lo ha appena pubblicato su Twitter. Dare un colpo, probabilmente funzionerà e non è troppo viscido – Bil

0

Forse si potrebbe utilizzare un attributo riservata per contenere il tipo di oggetto, e quindi utilizzare il tipo di base come indicato in questo articolo: Dynamic types with JSON.NET

1

Usando Json.net si può solo fare:

Dictionary<string,object> result = JsonConvert.DeserializeObject<Dictionary<string,object>>(json); 
foreach(var item in result) 
    Console.WriteLine(item.Key + " " + item.Value); 
1

Spero che l'esempio sottostante possa essere d'aiuto. Ho sempre progettato un modello che corrisponda al json. È molto meglio lavorare con l'oggetto quando è il tuo modello personale.

È molto semplice generare il modello C# da JSON. Io uso questo sito per generare il modello: http://json2csharp.com

Un esempio completo è:

C# Codice:

var targetsObject = Newtonsoft.Json.JsonConvert.DeserializeObject<YourModel>(jsonString); 

JSON:

{ 
     "investors": [ 
     { 
      "name": "06", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "6.0" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "07", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "7.0" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "08", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "7.0" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "09", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "10", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "2.0" 
      } 
      ] 
     }, 
     { 
      "name": "11", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "6.0" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "6.0" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "12", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "3.5" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "5.5" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "6.0" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "" 
      } 
      ] 
     }, 
     { 
      "name": "13", 
      "programs": [ 
      { 
       "name": "Conventional", 
       "value": "" 
      }, 
      { 
       "name": "FHA - Standard", 
       "value": "5.0" 
      }, 
      { 
       "name": "FHA - Streamline", 
       "value": "" 
      }, 
      { 
       "name": "VA", 
       "value": "" 
      }, 
      { 
       "name": "VA IRRRL", 
       "value": "" 
      }, 
      { 
       "name": "Non-Prime", 
       "value": "2.0" 
      } 
      ] 
     } 
     ] 
    } 

Modello:

public class Program 
    { 
     public string name { get; set; } 
     public string value { get; set; } 
    } 

    public class Investor 
    { 
     public string name { get; set; } 
     public List<Program> programs { get; set; } 
    } 

    public class RootObject 
    { 
     public List<Investor> investors { get; set; } 
    } 
Problemi correlati