JSON Nesne Dizisinin Json.net ile serisini kaldırma


118

Döndürülen json'lar için aşağıdaki örnek yapıyı kullanan bir API kullanmaya çalışıyorum

[
   {
      "customer":{
         "first_name":"Test",
         "last_name":"Account",
         "email":"test1@example.com",
         "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":"test2@example.com",
         "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 aşağıdaki yapı gibi bir şeyle harika çalışır

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

Ama sağlanan yapı ile onu nasıl mutlu edeceğimi bilemiyorum.

Varsayılan JsonConvert.DeserializeObject (içerik) kullanılması, doğru Müşteri sayısını verir, ancak tüm veriler boştur.

Bir Müşteri Listesi (aşağıda) bir şey yapmak, "Geçerli JSON dizisi seri durumdan çıkarılamıyor" istisnasına neden olur

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

Düşünceler?


Bu sorunuzu yanıtlıyor mu?
JSON'u

Yanıtlar:


187

Json'unuzu Serisini Kaldırmak için yeni bir model oluşturabilirsiniz 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; }

    ...
}

Ve json'unuzun seri halini kolayca kaldırabilirsiniz:

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

Umarım yardımcı olur !

Belgeler: JSON Seri Hale Getirme ve Seri Durumdan Çıkarma


1
Teşekkürler. Konuyu fazla düşündüm. İlk önce cevapladığınız gibi cevabınız kabul edildi.
Shawn C'de

2
JsonConvert.DeserializeObject <listesi <CustomerJson >> (json); Dize girdileri için mükemmel çalışır.
Markel Mairs

DeserializeObject()ARM çalıştıran android telefonlarda yavaştır. Bu dava için daha iyi bir çözüm var mı?
Tadej

1
Bir JObject ile gezinmeyi deneyinJObject.Parse(json);
Joffrey Kern

47

Herhangi bir model oluşturmak istemeyenler için aşağıdaki kodu kullanın:

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

Not: Bu işe yaramaz senin JSON dize. Bu, herhangi bir JSON yapısı için genel bir çözüm değildir .


10
Bu korkunç bir çözüm. Bunun yerine, model oluşturmak istemediyseniz,var result = JsonConvert.DeserializeObject<Tuple<string, string, string>>(content);
a11smiles

1
@ a11smiles Lütfen bunun neden korkunç bir çözüm olduğunu açıklayın.
Tyler Long

2
İlk olarak, farklı IEnumerableuygulama türleri için gereksiz bellek tahsisi (List <Tuple> ile karşılaştırıldığında 3). İkinci olarak, çözümünüz her sözlük için iki farklı anahtar gerektirir - 1. Birden çok müşteri aynı ada sahipse ne olur? Anahtarlarda herhangi bir fark olmayacaktı. Çözümünüz bu çatışmayı dikkate almıyor.
a11smiles

2
@ a11smiles her müşteri ayrı bir sözlüktür. Böylece aynı ada sahip birden fazla müşteri olsa bile herhangi bir sorun olmayacaktır.
Tyler Long

1
@ a11smiles Neden var result = JsonConvert.DeserializeObject<Tuple<string, string, string>>(content);işe yarayacağını düşündün merak ediyorum . Görünüşe göre işe yaramıyor
Tyler Long

1

Kabul edilen yanıtı kullanarak her bir kayda kullanarak erişmeniz Customers[i].customergerekir ve fazladan bir CustomerJsonsınıfa ihtiyacınız vardır, bu biraz can sıkıcıdır. Bunu yapmak istemiyorsanız, aşağıdakileri kullanabilirsiniz:

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

List<>Bir Dizi değil, a kullandığıma dikkat edin . Şimdi aşağıdaki sınıfı oluşturun:

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

Yukarıda belirtilenlere küçük bir değişiklik. Doğrulayan Json formatım

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

         }
       }

AlexDev'in cevabını kullanarak, bunu her çocuğu döngüye alarak, ondan okuyucu yaratarak yaptım

 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'dan daha fazla değişiklik yapın, sahip olduğu şeyi alın ve MyModelConverter'ı ...

public class MyModelConverter : JsonConverter
{
    //objectType is the type as specified for List<myModel> (i.e. myModel)
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader); //json from myModelList > model
        var list = Activator.CreateInstance(objectType) as System.Collections.IList; // new list to return
        var itemType = objectType.GenericTypeArguments[0]; // type of the list (myModel)
        if (token.Type.ToString() == "Object") //Object
        {
            var child = token.Children();
            var newObject = Activator.CreateInstance(itemType);
            serializer.Populate(token.CreateReader(), newObject);
            list.Add(newObject);
        }
        else //Array
        {
            foreach (var child in token.Children())
            {
                var newObject = Activator.CreateInstance(itemType);
                serializer.Populate(child.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();
}

Bu, json için de çalışmalıdır.

myModelList{
 model: [{ ... object ... }]
}

veya

myModelList{
 model: { ... object ... }
}

her ikisi de sanki öyleymiş gibi ayrıştırılacaklar

myModelList{
 model: [{ ... object ... }]
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.