2011-10-04 12 views
5

Utilizo DataContractJsonSerializer para analizar una cadena json en una jerarquía de objetos. El cadena JSON se ve así:C# DataContractJsonSerializer falla cuando el valor puede ser una matriz o un solo elemento

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

Como se puede ver el valor secundario de "atributos" puede ser una matriz o un solo elemento. He encontrado la parte de código, donde el problema occures:

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

Esto funciona para la primera pero no en el segundo.

¿Alguien tiene una respuesta para esto?

Thx

+0

¿por qué el json es inconsistente con esto? ¿sería posible arreglarlo en la fuente? –

+0

¿Cómo falla? ¿Qué error? – bryanmac

Respuesta

3

Si controlas cómo se crea la JSON a continuación, asegúrese de que se atribuye una gama aún más si sólo contiene un elemento. Entonces el segundo elemento se verá así y analizará bien.

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

Como dijo Daniel, si puede controlar la creación de Json, es mejor continuar de esa manera. Pero si no se puede, entonces se puede usar la biblioteca Json.Net & la clase JSONObject de this enlace a escribir algo de código como:

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

Esa es una buena idea +1 –

1

He intentado conseguir este trabajo con DataContractJsonSerializer, JavaScriptSerializer, y JSON .Net y ninguno se deserializarían directamente a un objeto con éxito en todos los casos. Usé un enfoque similar a L.B, usando JSON.Net, aunque sin el uso de la dinámica y la clase JsonObject adicional. La adaptación de mi código a su escenario sería algo como lo siguiente:

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

Con suerte, alguien va a añadir un escenario de JSON.Net para permitir que la fuerza de deserialización a una colección con un solo elemento en lugar de lanzar una excepción. Es una pena que tenga que hacer todo el análisis sintáctico manualmente cuando solo hay una pequeña porción del JSON que no se analiza automáticamente correctamente.

Cuestiones relacionadas