Mảng đối tượng JSON khử với Json.net


116

Tôi đang cố gắng sử dụng API sử dụng cấu trúc ví dụ sau cho json được trả về của họ

[
   {
      "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 sẽ hoạt động tốt với một cái gì đó giống như cấu trúc sau đây

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

Nhưng tôi không thể tìm ra cách làm cho nó hài lòng với cấu trúc được cung cấp.

Sử dụng JsonConvert.DeserializeObject (nội dung) mặc định cho kết quả đúng số lượng Khách hàng nhưng tất cả dữ liệu đều không có giá trị.

Làm một cái gì đó một Danh sách khách hàng (bên dưới) dẫn đến một ngoại lệ "Không thể khử lưu trữ mảng JSON hiện tại"

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

Suy nghĩ?


Điều này có trả lời câu hỏi của bạn không? Deserialize JSON với C #
GetFooked Weeb 16/12/19

Câu trả lời:


185

Bạn có thể tạo một mô hình mới để Deserialize Json của bạn 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; }

    ...
}

Và bạn có thể giải nén json của bạn một cách dễ dàng:

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

Hy vọng nó giúp !

Tài liệu: Tuần tự hóa và giải tuần tự JSON


1
Cảm ơn. Đã quá suy nghĩ vấn đề. Khi bạn trả lời đầu tiên, câu trả lời của bạn đã được chấp nhận.
Shawn C.

2
JsonConvert.DeserializeObject <Danh sách <CustomerJson >> (json); Hoạt động hoàn hảo cho đầu vào chuỗi.
Markel Mairs

DeserializeObject()chậm trên điện thoại Android chạy ARM. Bất kỳ giải pháp tốt hơn cho trường hợp đó?
Tadej

1
Cố gắng điều hướng với JObjectJObject.Parse(json);
Joffrey Kern

47

Đối với những người không muốn tạo bất kỳ mô hình nào, hãy sử dụng mã sau đây:

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

Lưu ý: Điều này không hoạt động cho chuỗi JSON của bạn . Đây không phải là một giải pháp chung cho bất kỳ cấu trúc JSON nào.


10
Đây là một giải pháp khủng khiếp. Thay vào đó, nếu bạn không muốn tạo mô hình, hãy sử dụngvar result = JsonConvert.DeserializeObject<Tuple<string, string, string>>(content);
a11smiles

1
@ a11smiles Hãy giải thích tại sao nó là một giải pháp khủng khiếp.
Tyler Long

2
Đầu tiên, phân bổ bộ nhớ không cần thiết cho các loại IEnumerabletriển khai khác nhau (3 so với Danh sách <Tuple>). Thứ hai, giải pháp của bạn bao hàm hai khóa riêng biệt - 1 cho mỗi từ điển. Điều gì xảy ra nếu nhiều khách hàng có cùng tên? Sẽ không có sự khác biệt trên các phím. Giải pháp của bạn không xem xét xung đột này.
a11smiles

2
@ a11smiles mỗi khách hàng là một từ điển riêng. Vì vậy, sẽ không có bất kỳ vấn đề nào ngay cả khi có nhiều khách hàng có cùng tên.
Tyler Long

1
@ a11smiles Tôi tự hỏi tại sao bạn nghĩ var result = JsonConvert.DeserializeObject<Tuple<string, string, string>>(content);sẽ làm việc. Rõ ràng là nó không hoạt động
Tyler Long

1

Sử dụng câu trả lời được chấp nhận, bạn phải truy cập từng bản ghi bằng cách sử dụng Customers[i].customervà bạn cần thêm một CustomerJsonlớp, điều này hơi khó chịu. Nếu bạn không muốn làm điều đó, bạn có thể sử dụng như sau:

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

Lưu ý rằng tôi đang sử dụng một List<>, không phải là một mảng. Bây giờ tạo lớp sau:

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

Sửa đổi nhẹ cho những gì đã nêu ở trên. Định dạng Json của tôi, xác nhận là

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

         }
       }

Sử dụng phản hồi của AlexDev, tôi đã thực hiện Điều này cho mỗi đứa trẻ, tạo ra người đọc từ nó

 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

Sửa đổi thêm từ JC_VA, lấy những gì anh ta có và thay thế MyModelConverter bằng ...

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();
}

Điều này sẽ làm việc cho json

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

hoặc là

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

cả hai cuối cùng sẽ bị phân tích cú pháp như thể họ đã

myModelList{
 model: [{ ... object ... }]
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.