2012-10-05 37 views
25

Json.Net通常將Dictionary<k,v>序列化爲集合;Json.Net - 序列化字典作爲數組(鍵值對)

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

這很好。而從環顧四周,這似乎是大多數人想要的。但是,在這種特殊情況下,我想在我的Dictionary<k,v>和Array格式之間進行序列化;

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

有沒有一種簡單的方法來做到這一點與我現有的字段類型?是否有我可以註釋的屬性?

回答

21

啊,事實證明這和我所希望的一樣簡單。我的Dictionary<k,v>已被分類,我發現我可以用[JsonArrayAttribute]對它進行註釋。這給了我完全我需要的格式;

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

在這個例子中,我將使用dictonary:

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

其序列化(與Newtonsoft.Json.JsonConvert.SerializeObject(myDict))到:

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

你可以做一個變換使用LINQ創建匿名對象,並序列化:

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

或者你可以使用一個真正的對象

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

和上述任一或替代LINQ語法:

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

無論哪種方式,這個序列化爲:

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

.NET小提琴鏈接:https://dotnetfiddle.net/LhisVW

1

gregmac的回答很有幫助,但並不奏效。以下是同樣的想法......沒有雙關語。

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

或課程

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

。然後以JSON

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

另一種方式來完成,這是使用自定義ContractResolver。這樣,您不必按照其他答案中的建議,繼承Dictionary<K,V>的子類,也不會在每次序列化時應用轉換。

下面的解析器將導致所有的字典被序列化作爲對象的數組與「鍵」和「值」屬性:

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

要使用的解析器,將它添加到您的JsonSerializerSettings,然後通過設置JsonConvert.SerializeObject()這樣的:

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

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

這裏是一個working demo

+0

現在爲序列化工作如何反序列化同一個對象 – MSTdev

+0

@MSTdev同樣的想法,使用'JsonConvert.DeserializeObject'並確保將解析器的'JsonSerializerSettings'傳遞給該方法。我更新了小提琴演示。 –

+0

@BrianRogers請檢查我的具體問題http://stackoverflow.com/questions/32473308/serialize-deserialization-issue-on-newton-json-for-idictionarymycustomclass-li – MSTdev

7

我找到的最簡單的解決方案是將您的Dictionary<string, string>轉換爲List<KeyValuePair<string, string>>。然後JSON.NET將您的List轉換爲{ Key: 'keyname', Value: 'value' }形式的對象數組。如果您接受所需的型號更改並且不想繼承您的Dictionary,則此方法可行。

+0

使用ToList()或ToArray()擴展方法使這個簡單。 –

相關問題