2011-10-04 1 views
5

uso la DataContractJsonSerializer per analizzare una stringa json in un hierarchie oggetto. stringa JSON è simile al seguente:C# DataContractJsonSerializer riesce quando valore può essere un array o un singolo elemento

{ 
    "groups": [ 
     { 
      "attributes": [ 
       { 
        "sortOrder": "1", 
        "value": "A" 
       }, 
       { 
        "sortOrder": "2", 
        "value": "B" 
       } 
      ] 
     }, 
     { 
      "attributes": { 
       "sortOrder": "1", 
       "value": "C" 
      } 
     } 
    ] 
} 

Come si può vedere il valore sub di "attributi" può essere un array o di un singolo elemento. Ho trovato la parte di codice in cui il problema occures:

[DataContract] 
public class ItemGroup 
{ 
    [DataMember(Name="attributes")] 
    public List<DetailItem> Items { get; set; } 
} 

Questo funziona per il primo, ma non riesce sul secondo.

Qualcuno ha una risposta per questo?

Thx

+0

Perché le incoerente JSON con questo? sarebbe possibile fissare-at-source? –

+0

Come fallisce? Che errore? – bryanmac

risposta

3

Se controlli come il JSON è creato quindi assicurarsi che attribuisce sia una matrice anche se contiene un solo elemento. Quindi il secondo elemento apparirà come questo e analizzerà bene.

{ 
     "attributes": [{ 
      "sortOrder": "1", 
      "value": "C" 
     }] 
    } 
3

Come detto Daniel, se è possibile controllare la creazione di JSON, è meglio continuare in questo modo. Ma se non è possibile, allora si può utilizzare Json.Net libreria & classe JsonObject da this link per scrivere del codice come:

JObject o = (JObject)JsonConvert.DeserializeObject(input); 
dynamic json = new JsonObject(o); 
foreach (var x in json.groups) 
{ 
     var attrs = x.attributes; 
     if (attrs is JArray) 
     { 
      foreach (var y in attrs) 
      { 
       Console.WriteLine(y.value); 
      } 
     } 
     else 
     { 
      Console.WriteLine(attrs.value); 
     } 
} 
+0

Questa è una buona idea +1 –

1

Ho cercato di ottenere questo lavoro con DataContractJsonSerializer, JavaScriptSerializer, e JSON .Net e nessuno potrebbe deserializzare direttamente su un oggetto con successo in tutti i casi. Ho usato un approccio simile a quello L.B, utilizzando JSON.Net, anche se senza l'uso delle dinamiche e della classe JsonObject supplementare. Adattare il mio codice per lo scenario sarebbe simile alla seguente:

private List<ItemGroup> ParseItemGroupList(string input) 
    { 
     JObject json = JObject.Parse(input); 

     List<ItemGroup> groups = new List<ItemGroup>(); 
     JArray gArray = json["groups"] as JArray; 
     foreach (var gToken in gArray) 
     { 
      ItemGroup newGroup = new ItemGroup(); 
      JToken attrToken = gToken["attributes"] as JToken; 
      if (attrToken is JArray) 
      { 
       newGroup.Items = attrToken.Children().Select(MapDetailItem()).ToList(); 
      } 
      else 
      { 
       newGroup.Items = new List<DetailItem>() { MapDetailItem().Invoke(attrToken) }; 
      } 

      groups.Add(newGroup); 
     } 

     return groups; 
    } 

    private static Func<JToken, DetailItem> MapDetailItem() 
    { 
     return json => new DetailItem 
     { 
      SortOrder = (string)json["sortOrder"], 
      Value = (string)json["value"] 
     }; 
    } 

Si spera, qualcuno aggiungerà un'impostazione per JSON.Net per consentirle di forzare deserializzazione ad una collezione con un singolo elemento, piuttosto che un'eccezione. E 'un peccato che si deve fare tutto il parsing manualmente quando c'è solo una piccola porzione del JSON che non analizza correttamente automaticamente.

Problemi correlati