使用Json.使用DataContractJsonSerializer使用的结构来(反)序列化字典

本文关键字:使用 字典 序列化 结构 Json DataContractJsonSerializer | 更新日期: 2023-09-27 18:06:37

是否有办法使用Json。. NET进行(反)序列化,但继续使用DataContractJsonSerializer的字典序列化约定?

换句话说,有没有办法在这个结构中读写JSON:

{ "MyDict" : [
    { "Key" : "One",
      "Value" : 1 },
    { "Key" : "Two",
      "Value" : 2 }
    ] }

使用像这样的类(Json)。NET属性):

public class MyClass
{
    public Dictionary<string, int> MyDict { get; set; }
}

好像是Json。. NET的KeyValuePairConverter可能会有所帮助,但如果是这样,我找不到正确的方法来应用它。

我尝试将MyDict归因于[JsonProperty(ItemConverterType = typeof(KeyValuePairConverter))],本页甚至似乎暗示可以工作,但在序列化期间添加这样的属性会导致ArgumentOutOfRangeException

使用Json.使用DataContractJsonSerializer使用的结构来(反)序列化字典

你是对的,KeyValuePairConverter在这里似乎不能正常工作。无需深入研究Json。Net源代码,我只能推测为什么。作为一种解决方法,您可以创建自己的自定义JsonConverter来很容易地完成此翻译:

class MyDictionaryConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Dictionary<string, T>));
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = JArray.Load(reader);
        Dictionary<string, T> dict = new Dictionary<string, T>();
        foreach (JObject obj in array.Children<JObject>())
        {
            string key = obj["Key"].ToString();
            T val = obj["Value"].ToObject<T>();
            dict.Add(key, val);
        }
        return dict;
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Dictionary<string, T> dict = (Dictionary<string, T>)value;
        JArray array = new JArray();
        foreach (KeyValuePair<string, T> kvp in dict)
        {
            JObject obj = new JObject();
            obj.Add("Key", kvp.Key);
            obj.Add("Value", JToken.FromObject(kvp.Value));
            array.Add(obj);
        }
        array.WriteTo(writer);
    }
}

使用[JsonConverter]属性将转换器应用于字典:

public class MyClass
{
    [JsonConverter(typeof(MyDictionaryConverter<int>))]
    public Dictionary<string, int> MyDict { get; set; }
}

下面是一个简短的演示程序,展示了转换器的运行(完整的往返):

class Program
{
    static void Main(string[] args)
    {
        MyClass mc = new MyClass { MyDict = new Dictionary<string, int>() };
        mc.MyDict.Add("One", 1);
        mc.MyDict.Add("Two", 2);
        string json = JsonConvert.SerializeObject(mc, Formatting.Indented);
        Console.WriteLine(json);
        Console.WriteLine();
        MyClass mc2 = JsonConvert.DeserializeObject<MyClass>(json);
        foreach (KeyValuePair<string, int> kvp in mc2.MyDict)
        {
            Console.WriteLine(kvp.Key + " == " + kvp.Value);
        }
    }
}

以上输出:

{
  "MyDict": [
    {
      "Key": "One",
      "Value": 1
    },
    {
      "Key": "Two",
      "Value": 2
    }
  ]
}
One == 1
Two == 2