web-dev-qa-db-fra.com

Deserializing JSON Object Array avec Json.net

Je tente d'utiliser une API qui utilise la structure exemple suivante pour leur JSON retourné

[
   {
      "customer":{
         "first_name":"Test",
         "last_name":"Account",
         "email":"[email protected]",
         "organization":"",
         "reference":null,
         "id":3545134,
         "created_at":"2013-08-06T15:51:15-04:00",
         "updated_at":"2013-08-06T15:51:15-04:00",
         "address":"",
         "address_2":"",
         "city":"",
         "state":"",
         "Zip":"",
         "country":"",
         "phone":""
      }
   },
   {
      "customer":{
         "first_name":"Test",
         "last_name":"Account2",
         "email":"[email protected]",
         "organization":"",
         "reference":null,
         "id":3570462,
         "created_at":"2013-08-12T11:54:58-04:00",
         "updated_at":"2013-08-12T11:54:58-04:00",
         "address":"",
         "address_2":"",
         "city":"",
         "state":"",
         "Zip":"",
         "country":"",
         "phone":""
      }
   }
]

JSON.net fonctionnerait très bien avec quelque chose comme la structure suivante 

{
    "customer": {
        ["field1" : "value", etc...],
        ["field1" : "value", etc...],
    }
}

Mais je ne peux pas comprendre comment le rendre heureux avec la structure fournie. 

L'utilisation du nom par défaut JsonConvert.DeserializeObject (contenu) donne le nombre correct de clients, mais toutes les données sont nulles.

Faire quelque chose comme CustomerList (ci-dessous) entraîne une exception "Impossible de désérialiser le tableau JSON actuel"

public class CustomerList
{
    public List<Customer> customer { get; set; }
}

Pensées?

99
Shawn C.

Vous pouvez créer un nouveau modèle pour désérialiser votre Json CustomerJson:

public class CustomerJson
{
    [JsonProperty("customer")]
    public Customer Customer { get; set; }
}

public class Customer
{
    [JsonProperty("first_name")]
    public string Firstname { get; set; }

    [JsonProperty("last_name")]
    public string Lastname { get; set; }

    ...
}

Et vous pouvez désérialiser facilement votre JSON:

JsonConvert.DeserializeObject<List<CustomerJson>>(json);

J'espère que ça aide !

Documentation: Sérialisation et désérialisation JSON

160
Joffrey Kern

Pour ceux qui ne veulent pas créer de modèles, utilisez le code suivant:

var result = JsonConvert.DeserializeObject<
  List<Dictionary<string, 
    Dictionary<string, string>>>>(content);
41
Tyler Long

En utilisant la réponse acceptée, vous devez accéder à chaque enregistrement en utilisant Customers[i].customer. Vous avez besoin d'une classe CustomerJson supplémentaire, ce qui est un peu gênant. Si vous ne voulez pas faire cela, vous pouvez utiliser ce qui suit:

public class CustomerList
{
    [JsonConverter(typeof(MyListConverter))]
    public List<Customer> customer { get; set; }
}

Notez que j'utilise un List<>, pas un tableau. Maintenant, créez la classe suivante:

class MyListConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        var list = Activator.CreateInstance(objectType) as System.Collections.IList;
        var itemType = objectType.GenericTypeArguments[0];
        foreach (var child in token.Values())
        {
            var childToken = child.Children().First();
            var newObject = Activator.CreateInstance(itemType);
            serializer.Populate(childToken.CreateReader(), newObject);
            list.Add(newObject);
        }
        return list;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType.IsGenericType && (objectType.GetGenericTypeDefinition() == typeof(List<>));
    }
    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
}
1
AlexDev

Légère modification de ce qui a été dit ci-dessus. Mon format Json, qui valide était 

{
    mycollection:{[
           {   
               property0:value,
               property1:value,
             },
             {   
               property0:value,
               property1:value,
             }
           ]

         }
       }

En utilisant la réponse d’AlexDev, j’ai fait cela en boucle chaque enfant, créant ainsi un lecteur

 public partial class myModel
{
    public static List<myModel> FromJson(string json) => JsonConvert.DeserializeObject<myModelList>(json, Converter.Settings).model;
}

 public class myModelList {
    [JsonConverter(typeof(myModelConverter))]
    public List<myModel> model { get; set; }

}

class myModelConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        var list = Activator.CreateInstance(objectType) as System.Collections.IList;
        var itemType = objectType.GenericTypeArguments[0];
        foreach (var child in token.Children())  //mod here
        {
            var newObject = Activator.CreateInstance(itemType);
            serializer.Populate(child.CreateReader(), newObject); //mod here
            list.Add(newObject);
        }
        return list;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType.IsGenericType && (objectType.GetGenericTypeDefinition() == typeof(List<>));
    }
    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();

}
0
JC_VA