Json.Net通常将Dictionary<k,v>
序列化为集合;
"MyDict": {
"Apples": {
"Taste": 1341181398,
"Title": "Granny Smith",
},
"Oranges": {
"Taste": 9999999999,
"Title": "Coxes Pippin",
},
}
哪个好。从环顾四周看似乎是大多数人想要的东西。但是,在这种特殊情况下,我想在我的Dictionary<k,v>
和数组格式之间进行序列化,而不是
"MyDict": [
"k": "Apples",
"v": {
"Taste": 1341181398,
"Title": "Granny Smith",
}
},
"k:": "Oranges",
"v:": {
"Taste": 9999999999,
"Title": "Coxes Pippin",
}
},
]
使用现有的字段类型有一种简单的方法吗?是否有我可以注释的属性?
答案 0 :(得分:33)
另一种方法是使用自定义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。
答案 1 :(得分:24)
啊,事实证明这和我希望的一样简单。我的Dictionary<k,v>
已经被子类化,我发现我可以使用[JsonArrayAttribute]
对其进行注释。这给了我完全符合我需要的格式;
"MyDict": [
{
"Key": "Apples",
"Value": {
"Taste": 1341181398,
"Title": "Granny Smith",
}
},
{
"Key:": "Oranges",
"Value:": {
"Taste": 9999999999,
"Title": "Coxes Pippin",
}
},
]
答案 2 :(得分:12)
对于这个例子,我将使用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
答案 3 :(得分: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() } )
答案 4 :(得分:0)
我不确定为什么,但是上面列出的Brian Brians定制的ContractResolver对我不起作用。它似乎在内部某个地方陷入了无限循环。可能是由于我的json.net设置的其他部分。
无论如何-这种解决方法对我有用。
public interface IStrongIdentifier
{
string StringValue { get; set; }
}
public class StrongIdentifierKeyedDictionaryWrapper<TKey, TValue> : Dictionary<string, TValue>
where TKey : IStrongIdentifier
{
public void Add(TKey key, TValue value)
{
base.Add(key.StringValue, value);
}
public void Remove(TKey key)
{
base.Remove(key.StringValue);
}
public TValue this[TKey index]
{
get => base[index.StringValue];
set => base[index.StringValue] = value;
}
public bool ContainsKey(TKey key)
{
return base.ContainsKey(key.StringValue);
}
}