如何反序列化为IREADONLY字典C#

时间:2015-07-14 17:36:28

标签: c# json json-deserialization

我正在尝试反序列化json

{
  "Type": "Correction",
  "StartTime": "2007-12-19T03:00:00.0000000-08:00",
  "EndTime": "2007-12-23T23:00:00.0000000-08:00",
  "Parameters": [
    {
      "Key": "Something",
      "Value": "1.8"
    },
    {
      "Key": "Something2",
      "Value": "0.10000000000000001"
    },
    {
      "Key": "Something3",
      "Value": "answer3"
    },
  ],
}

加入包含public IReadOnlyDictionary<string, string> Parameters { get; set; }的Dto 以及许多其他事情。

我正在使用最新的newtonsoft反序列化器,功能

var responseObject = JsonConvert.DeserializeObject<TResponse>(jsonResponse);

但它返回错误

Newtonsoft.Json.JsonSerializationException : Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.String]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

是否有任何工具可用于帮助将Json响应更改为不同的响应,例如

"Parameters": 
    {
      "Something": "1.8",
      "Something2": "0.10000000000000001",
      "Something3": "answer3",
    },

有效(因为数组被删除)。

P.S。我已经使用了正则表达式替换,但由于最小的json更改可能导致它失败,我已经放弃了这种方法。

谢谢!

2 个答案:

答案 0 :(得分:2)

好的,这花了我一段时间,但我明白了。

所以简短的回答是,如果可能的话,使用面向.NET v4.5 +的NewtonSoft.Json版本。但是,如果您的应用程序要在.NET 4.5及更低版本上运行,则无法使用此功能。

您遇到此错误的原因是因为您的NewtonSoft.Json针对v4.5以下的.NET框架。这是因为在.NET v4.5中引入了IReadonlyDictionaryThis是2013年的博客文章,在NewtonSoft 5.0中为.NET v4.5引入了这一新功能。

newtonsoft.json nuget包中,有多个版本的程序集针对不同的.NET版本。我使用ildasm来查看程序集元数据。

对于packages\Newtonsoft.Json.<version>\lib\net40\Newtonsoft.Json.dll,它将TargetFramework设置为v4.0,其实现不支持支持反序列化为IReadonlyDictionary

.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework 2C 56 65 72 73 69 6F 6E 3D 76 34 2E 30 01 00 54 // ,Version=v4.0..T 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl 61 79 4E 61 6D 65 10 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram 65 77 6F 72 6B 20 34 ) // ework 4

对于packages\Newtonsoft.Json.<version>\lib\net45\Newtonsoft.Json.dll,它将TargetFramework设置为v4.5,其实现支持支持反序列化为IReadonlyDictionary

.custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1A 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework 2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 01 00 54 // ,Version=v4.5..T 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C // ..FrameworkDispl 61 79 4E 61 6D 65 12 2E 4E 45 54 20 46 72 61 6D // ayName..NET Fram 65 77 6F 72 6B 20 34 2E 35 ) // ework 4.5

我甚至检查了一个针对.NET 4.5的非常旧版本的Newtonsoft.Json(v6.0),它确实支持只读字典。

答案 1 :(得分:1)

您可以编写自定义JsonConverter

public class KVListToDictConverter<T1,T2> : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(Dictionary<T1, T2>) == objectType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
            if (reader.TokenType == JsonToken.StartArray)
                return serializer.Deserialize<List<KeyValuePair<T1, T2>>>(reader).ToDictionary(x => x.Key, x => x.Value);
            else
            {
                var c = serializer.Converters.First();
                serializer.Converters.Clear(); //to avoid infinite recursion
                var dict =  serializer.Deserialize<Dictionary<T1, T2>>(reader);
                serializer.Converters.Add(c);
                return dict;
            }
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

并用于反序列化,如

var json = JsonConvert.DeserializeObject<YourObject>(json, new KVListToDictConverter<string,string>());

这既适用于您的第一个json,也适用于您希望使用正则表达式的json。