将字典序列化为数组(键值对)

cir*_*rus 32 c# json.net

Json.Net通常将a序列Dictionary<k,v>化为集合;

"MyDict": {
  "Apples": {
    "Taste": 1341181398,
    "Title": "Granny Smith",
  },
  "Oranges": {
    "Taste": 9999999999,
    "Title": "Coxes Pippin",
  },
 }
Run Code Online (Sandbox Code Playgroud)

哪个好.从环顾四周看似乎是大多数人想要的东西.但是,在这种特殊情况下,我想在我的Dictionary<k,v>和Array格式之间进行序列化;

"MyDict": [
    "k": "Apples",
    "v": {
        "Taste": 1341181398,
        "Title": "Granny Smith",
    }
  },
    "k:": "Oranges",
    "v:": {
        "Taste": 9999999999,
        "Title": "Coxes Pippin",
    }
  },
]
Run Code Online (Sandbox Code Playgroud)

使用我现有的字段类型有一种简单的方法吗?有没有我可以注释的属性?

Bri*_*ers 36

另一种方法是使用自定义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);
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用解析器,请将其添加到您JsonSerializerSettings的设置,然后将设置传递给您JsonConvert.SerializeObject():

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

string json = JsonConvert.SerializeObject(obj, settings);
Run Code Online (Sandbox Code Playgroud)

这是一个工作演示.


cir*_*rus 24

啊,事实证明这和我希望的一样简单.我Dictionary<k,v>的子类已经存在,我发现我可以用它进行注释[JsonArrayAttribute].这给了我完全我需要的格式;

"MyDict": [
  {
    "Key": "Apples",
    "Value": {
        "Taste": 1341181398,
        "Title": "Granny Smith",
    }
  },
  {
    "Key:": "Oranges",
    "Value:": {
        "Taste": 9999999999,
        "Title": "Coxes Pippin",
    }
  },
]
Run Code Online (Sandbox Code Playgroud)

  • 有没有一种方法可以使用 Json.NET 配置来展平 Key 和 Value 属性(成为顶级数组中对象的一个​​属性)? (2认同)

gre*_*mac 12

对于这个例子,我将使用dictonary:

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

序列化(与Newtonsoft.Json.JsonConvert.SerializeObject(myDict)):

{"a":"123","b":"234","c":"345"}
Run Code Online (Sandbox Code Playgroud)

您可以使用LINQ进行转换以创建匿名对象,并序列化:

 var myDictTransformed = from key in myDict.Keys
                         select new { k = key, v = myDict[key] };
Run Code Online (Sandbox Code Playgroud)

或者您可以使用真实对象

class MyDictEntry 
{
    public string k { get; set; }
    public string v { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

以及上面或替代的LINQ语法:

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

无论哪种方式,这序列化为:

[
  {"k":"a", "v":"123"},
  {"k":"b", "v":"234"},
  {"k":"c", "v":"345"}
]
Run Code Online (Sandbox Code Playgroud)

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


Swo*_*gan 11

我找到的最简单的解决方案是将您转换Dictionary<string, string>List<KeyValuePair<string, string>>.然后JSON.NET将您List转换为带有表单的对象数组{ Key: 'keyname', Value: 'value' }.如果您接受所需的模型更改并且不想继承您的模型,则此方法很有效Dictionary.