WCF & WebAPI 序列化 Dictionary 物件到 Json 的格式問題

最近同事遇到一個問題,在 WCF 跟 ASP.NET MVC 4 的 WebAPI 下回傳 Dictionary 的物件的時候和 Json.net 序列化的結果不同,回傳的格式也不是那麼方便使用。

WCF & WebAPI 回傳 Dictionary 的格式

利用 Web API 建立

public object Get()
{
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("key1", "value1");
dic.Add("key2", "value2");
return dic;
}

他回傳的格式會是

[
{
Key: "key1",
Value: "value1"
},
{
Key: "key2",
Value: "value2"
}
]

但是這樣子回傳的 Json 物件在 Javascript 下並不方便直接使用,沒辦法用 object.key1 直接取值,或是 object[“key1”] 也沒辦法。比較理想的回傳格式應該是

{
"key1": "value1",
"key2": "value2"
}

解決方法

這個問題是 WCF & Web API 再回傳的時候序列化元件的邏輯處理的,其實嚴格來說並不是 Bug ,只是不好用而已,當然有其他幾種方法來處理。

  1. 直接組字串
  2. 回傳的時候用 Json.NET 序列化之後再回傳

這兩種都不是很好的做法,有點失去 WCF & Web API 原本的用意。

第三種作法

利用自訂的 class 去改變序列化的邏輯,在這邊我們建立

[Serializable]
public class JsonDictionary : ISerializable
{
Dictionary<string, object> dict = new Dictionary<string, object>();
public JsonDictionary() { }
public JsonDictionary(Dictionary<string, object> dic)
{
this.dict = dic;
}
protected JsonDictionary(SerializationInfo info, StreamingContext context)
{
foreach (var entry in info)
{
dict.Add(entry.Name, entry.Value);
}
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (string key in dict.Keys)
{
info.AddValue(key, dict[key], dict[key] == null ? typeof(object) : dict[key].GetType());
}
}

public void Add(string key, object value)
{
dict.Add(key, value);
}

public static explicit operator JsonDictionary(Dictionary<string, object> dic)
{
return new JsonDictionary(dic);
}
}

改變 GetObjectData 用以取代原先序列化的邏輯,並且加上 explicit operator 方便跟 Dictionary 做轉型的動作。

改寫之後的 Web API

public object Get()
{
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("key1", "value1");
dic.Add("key2", "value2");
return (JsonDictionary)dic;
}

在這邊再回傳的時候先轉型為剛剛自訂的 JsonDictionary ,可以發現的是一開始我就設定回傳型別為 object ,只是為了讓這個方法看起來比較好用一些。回傳前轉型回傳型態也是要跟著改變的。

{
"key1": "value1",
"key2": "value2"
}

這樣回傳的時候就會是想要的格式了。


JSON deserializer does not deserialize a Dictionary correctly

c# – .NET WCF Json deserializing a Dictionary<int, int> – Stack

c#WCF – POST JSON Dictionary without Key/Value Text – Stack

c# – Make ASP.NET WCF convert dictionary to JSON, omitting “Key

WCF JSON Serialization is flawed « Duncan Smart’s Weblog

.NET by Example: JSON services revisited: using a Dictionary as a

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *