简体   繁体   English

C# 使用 JSON.NET 反序列化字典 <(Enum,Enum),string>

[英]C# Deserializing a Dictionary<(Enum,Enum),string> with JSON.NET

I've been struggling to deserialize a Dictionary with Enum Tuple keys in Json.Net.我一直在努力用 Json.Net 中的枚举元组键反序列化字典。 The main problem is that the deserializer can't convert the values back to the specified Enum Tuple whether it's the Enum's string or integer representation in the Json.主要问题是反序列化器无法将值转换回指定的 Enum 元组,无论它是 Enum 的字符串还是 Json 中的 integer 表示。

I've tried these solutions but none of the worked:我已经尝试了这些解决方案,但都没有奏效:

  1. https://stackoverflow.com/a/59310390 https://stackoverflow.com/a/59310390
  2. https://gist.github.com/SteveDunn/e355b98b0dbf5a0209cb8294f7fffe24 https://gist.github.com/SteveDunn/e355b98b0dbf5a0209cb8294f7fffe24

Tried to write my own Custom Converter, the WriteJson part works, but I can't even stop the ReadJson function with breakpoints to see what happens inside.尝试编写我自己的自定义转换器,WriteJson 部分有效,但我什至无法用断点停止 ReadJson function 以查看内部发生的情况。

I'd be happy to get some help with the issue.我很乐意在这个问题上得到一些帮助。 Maybe somebody already has a solution.也许有人已经有了解决方案。

The JSON looks like this: JSON 看起来像这样:

{
   "DictionaryProperty":{
      "(EnumType1Value1, EnumType2Value1)":"New",
      "(EnumType1Value1, EnumType2Value1)":"Old",
      "(EnumType1Value2, EnumType2Value1)":"Newer",
      "(EnumType1Value2, EnumType2Value2)":"Older"
}

This is the error I get:这是我得到的错误:

"Could not convert string '(EnumType1Value1, EnumType2Value1)' to dictionary key type 'System.ValueTuple`2[EnumType1,EnumType2]'" “无法将字符串 '(EnumType1Value1, EnumType2Value1)' 转换为字典键类型 'System.ValueTuple`2[EnumType1,EnumType2]'”

This is the custom converter I wrote:这是我写的自定义转换器:

public class CustomDictionaryConverter : JsonConverter<Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string>>
{
    public override void WriteJson(JsonWriter writer, Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, ((Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string>)value).ToList());
    }

    public override Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> ReadJson(
        JsonReader reader
        , Type objectType
        , Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> existingValue
        , bool hasExistingValue
        , JsonSerializer serializer)
    {
        Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> tempdict = new Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string>();

        var temp = serializer.Deserialize<Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string>[]>(reader)[0];

        tempdict = (Dictionary<(EnumType1 Enum1, EnumType2  Enum2), string>)temp;
        return tempdict;
    }
}

A bit manual (and lacking decent error checking), but works for your specified json both serializing & deserializing有点手动(并且缺乏体面的错误检查),但适用于您指定的 json 序列化和反序列化

public class CustomDictionaryConverter : JsonConverter<Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string>>
{
    public override void WriteJson(JsonWriter writer, Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> value, JsonSerializer serializer)
    {
        writer.WriteStartObject();
        foreach(var kv in value)
        {
            writer.WritePropertyName($"({kv.Key.Enum1.ToString()},{kv.Key.Enum2.ToString()})");
            writer.WriteValue(kv.Value);
        }
        writer.WriteEndObject();
    }

    public override Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> ReadJson(
        JsonReader reader
        , Type objectType
        , Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> existingValue
        , bool hasExistingValue
        , JsonSerializer serializer)
    {
        Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string> tempdict = new Dictionary<(EnumType1 Enum1, EnumType2 Enum2), string>();
        JObject jObject = JObject.Load(reader);
        foreach(var kv in ((IEnumerable<KeyValuePair<string, JToken>>)jObject)) 
        {
            var keys = kv.Key.Replace("(","").Replace(")","").Split(",");
            var key1 = Enum.Parse<EnumType1>(keys[0]);
            var key2 = Enum.Parse<EnumType2>(keys[1]);
            var value = kv.Value.ToString();
            tempdict.Add((key1,key2),value);
        }
        return tempdict;
    }
}

Live example: https://do.netfiddle.net/w85HgK现场示例: https://do.netfiddle.net/w85HgK

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM