【问题标题】:Deserialising JSON using JsonSerializer.DeserializeAsync is not using my JsonConverter使用 JsonSerializer.DeserializeAsync 反序列化 JSON 不使用我的 JsonConverter
【发布时间】:2019-10-03 10:45:39
【问题描述】:

服务器正在返回一个 JSON 字符串值,它是一个 URL 查询字符串:

{
    "parameters": "key1=value1&key2=value2"
}

我设置了一个属性来接收它,并将其转换为 Dictionary 作为反序列化过程的一部分:

具有JsonConverter 属性的属性:

[JsonConverter(typeof(QueryStringToDictionaryJsonConverter))]
public Dictionary<string, string> Parameters { get; set; }

转换器:

public class QueryStringToDictionaryJsonConverter : JsonConverter<Dictionary<string, string>> {

    public override Dictionary<string, string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {

        var queryString = reader.GetString();
        if (string.IsNullOrEmpty(queryString)) return null;

        return QueryHelpers.ParseQuery(queryString).ToDictionary(e => e.Key, e => string.Join(",", e.Value.ToArray()));

    }

    ...
}

这应该可行。

但它甚至没有到达我的转换器。

据我所知,JsonSerializer.DeserializeAsync&lt;T&gt;(myJson) 看到属性的类型是 Dictionary,因此它尝试自行解析值,但失败(结果异常是“无效类型转换” ' 因为它试图 GetEnumerable() 等)。我的转换器中的断点甚至都不会被命中。

我可以通过将属性设置为 object 并在稍后使用它时转换为 Dictionary 来使其工作,但这是一个丑陋的解决方案。

有没有办法强制JsonSerializer.DeserializeAsync&lt;T&gt;(myJson) 只使用我的转换器,而不是让它自己变得聪明?

(我在 .NET Core 3 中使用微软的 System.Text.Json)

【问题讨论】:

  • github.com/dotnet/corefx/issues/40405 - 这听起来像您遇到的问题吗?
  • @theduck 是的,谢谢,这听起来确实是个问题,虽然它说它是针对 3.0 修复的,但显然我发现不是这种情况 :-(

标签: c# .net json deserialization system.text.json


【解决方案1】:

好的,所以这可能是System.Text.Json 中的一个错误。

这是我目前为其他需要解决方案的人使用的解决方法。

首先,我为反序列化设置了两个属性,分别使用[JsonPropertyName][JsonIgnore]

[JsonPropertyName("parameters"), JsonConverter(typeof(QueryStringToDictionaryJsonConverter))]
public object ParametersObject { get; set; }

[JsonIgnore]
public Dictionary<string, string> Parameters => ParametersObject as Dictionary<string, string>;

然后在JsonConverter 中,我允许object 作为类型:

public override bool CanConvert(Type typeToConvert) {
    if (typeToConvert == typeof(object)) return true;
    return base.CanConvert(typeToConvert);
}

我的反序列化类的使用者只需使用 Parameters 属性,如果修复此错误并且我将类更改回我想要的方式,它将继续正常工作。

【讨论】:

    【解决方案2】:

    我会创建一个包装器并为该包装器创建一个转换器。

    [JsonConverter( typeof( QueryStringDictionaryConverter ) )]
    class QueryStringDictionary : Dictionary<string,string> { }
    
    class QueryStringDictionaryConverter : JsonConverter<QueryStringDictionary>
    {
        ... 
    }
    
    class MyClass
    {
        public QueryStringDictionary Parameters { get; set; }
    }
    

    您也可以使用JsonSerializerOptions

    class MyOtherClass
    {
       public Dictionary<string,string> Parameters { get; set; }
    }
    MyOtherClass Deserialize( string json )
    {
        var options = new JsonSerializerOptions
        {
            Converters = { new QueryStringToDictionaryJsonConverter() }
        };
        return JsonSerializer.Deserialize<MyOtherClass>( json, options );  
    } 
    

    这种方法的一个潜在问题是转换器将用于所有Dictionary&lt;string,string&gt; 属性,这可能不是有意的。它适用于原始问题中的简单示例。

    【讨论】:

      猜你喜欢
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 1970-01-01
      • 2011-03-15
      • 2022-01-03
      相关资源
      最近更新 更多