2012-10-05 28 views
25

Json.Net thường tuần tự hóa Dictionary<k,v> thành một bộ sưu tập;Json.Net - Serialize Dictionary as Array (của cặp giá trị chính)

"MyDict": { 
    "Apples": { 
    "Taste": 1341181398, 
    "Title": "Granny Smith", 
    }, 
    "Oranges": { 
    "Taste": 9999999999, 
    "Title": "Coxes Pippin", 
    }, 
} 

Điều này thật tuyệt. Và từ nhìn xung quanh trên SO nó có vẻ là những gì hầu hết mọi người muốn. Tuy nhiên, trong trường hợp cụ thể này, tôi muốn tuần tự hóa giữa Dictionary<k,v> và định dạng Mảng thay thế;

"MyDict": [ 
    "k": "Apples", 
    "v": { 
     "Taste": 1341181398, 
     "Title": "Granny Smith", 
    } 
    }, 
    "k:": "Oranges", 
    "v:": { 
     "Taste": 9999999999, 
     "Title": "Coxes Pippin", 
    } 
    }, 
] 

Có cách nào dễ dàng để thực hiện việc này với loại trường hiện tại của tôi không? Có một thuộc tính tôi có thể chú thích ví dụ?

Trả lời

21

Ah, hóa ra điều này đơn giản như tôi mong đợi. My Dictionary<k,v> đã được phân loại rồi và tôi thấy rằng tôi có thể chú thích nó với [JsonArrayAttribute]. Điều đó mang lại cho tôi chính xác định dạng tôi cần;

"MyDict": [ 
    { 
    "Key": "Apples", 
    "Value": { 
     "Taste": 1341181398, 
     "Title": "Granny Smith", 
    } 
    }, 
    { 
    "Key:": "Oranges", 
    "Value:": { 
     "Taste": 9999999999, 
     "Title": "Coxes Pippin", 
    } 
    }, 
] 
11

Đối với ví dụ này, tôi sẽ sử dụng dictonary:

var myDict = new Dictionary<string,string>() { 
    {"a","123"}, 
    {"b","234"}, 
    {"c","345"} 
}; 

mà serializes (với Newtonsoft.Json.JsonConvert.SerializeObject(myDict)) tới:

{"a":"123","b":"234","c":"345"} 

Bạn có thể làm một chuyển đổi sử dụng LINQ để tạo ra một đối tượng ẩn danh và tuần tự hóa:

var myDictTransformed = from key in myDict.Keys 
         select new { k = key, v = myDict[key] }; 

Hoặc bạn có thể sử dụng một đối tượng thực

class MyDictEntry 
{ 
    public string k { get; set; } 
    public string v { get; set; } 
} 

và một trong hai ở trên hoặc cú pháp LINQ thay thế:

var myDictTransformed = myDict.Keys.AsEnumerable() 
         .Select(key => new MyDictEntry{ 
          k = key, 
          v = myDict[key] 
         }); 

Dù bằng cách nào, điều này serializes đến:

[ 
    {"k":"a", "v":"123"}, 
    {"k":"b", "v":"234"}, 
    {"k":"c", "v":"345"} 
] 

Liên kết .NET Fiddle: https://dotnetfiddle.net/LhisVW

1

Câu trả lời của gregmac hữu ích nhưng không hoạt động. Sau đây là ý tưởng tương tự ... mà không có chơi chữ.

var dictionaryTransformed = dictionary.Select(item => item.Key).Select(i => 
         new {Key = i, Value = dictionary[i] }); 

hoặc tất nhiên

var dictionaryTransformed = dictionary.Select(item => 
         new {item.Key, Value = dictionary[item.Key] }); 

Sau đó, để JSON

var json = (new JavaScriptSerializer()).Serialize( 
         new { Container = dictionaryTransformed.ToArray() }) 
27

Một cách khác để thực hiện điều này là sử dụng một tùy chỉnh ContractResolver. Bằng cách đó bạn không phải phân lớp Dictionary<K,V> cũng không áp dụng biến đổi mỗi lần bạn sắp xếp theo thứ tự, như được đề xuất trong các câu trả lời khác.

Các thống xử lý sau đây sẽ gây ALL từ điển để được tuần tự như một mảng của các đối tượng với "chính" và "Giá trị" tài sản:

class DictionaryAsArrayResolver : DefaultContractResolver 
{ 
    protected override JsonContract CreateContract(Type objectType) 
    { 
     if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) || 
      (i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>)))) 
     { 
      return base.CreateArrayContract(objectType); 
     } 

     return base.CreateContract(objectType); 
    } 
} 

Để sử dụng phân giải, thêm nó vào JsonSerializerSettings của bạn, sau đó vượt qua thiết lập để JsonConvert.SerializeObject() như thế này:

JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.ContractResolver = new DictionaryAsArrayResolver(); 

string json = JsonConvert.SerializeObject(obj, settings); 

đây là một working demo.

+0

Làm việc cho serialization, bây giờ Làm thế nào để deserialize cùng một đối tượng – MSTdev

+0

@MSTdev Cùng một ý tưởng, sử dụng 'JsonConvert.DeserializeObject' và chắc chắn vượt qua' JsonSerializerSettings' với người giải quyết cho phương pháp đó. Tôi cập nhật fiddle để chứng minh. –

+0

@BrianRogers vui lòng kiểm tra vấn đề chi tiết của tôi http://stackoverflow.com/questions/32473308/serialize-deserialization-issue-on-newton-json-for-idictionarymycustomclass-li – MSTdev

7

Giải pháp đơn giản nhất tôi tìm thấy là chuyển đổi Dictionary<string, string> thành List<KeyValuePair<string, string>>. JSON.NET sau đó chuyển đổi List của bạn thành một mảng các đối tượng có dạng { Key: 'keyname', Value: 'value' }. Điều này hoạt động tốt nếu bạn chấp nhận thay đổi mô hình bắt buộc và không muốn phân lớp Dictionary của mình.

+0

Sử dụng phương thức mở rộng ToList() hoặc ToArray() làm cho dễ dàng. –

Các vấn đề liên quan