使用JsonSerializer反序列化JSON.DeserializeAsync不使用我的JsonConverter

时间:2019-10-03 10:45:39

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

服务器返回的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<T>(myJson)看到属性的类型为Dictionary,因此它尝试自行解析值,并失败(结果异常是尝试GetEnumerable()等时使用“无效类型转换”)。我的转换器中的断点甚至都不会命中。

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

是否有一种方法可以强制JsonSerializer.DeserializeAsync<T>(myJson)只使用我的转换器,而不必试图自己变得聪明?

(我正在.NET Core 3中使用Microsoft的System.Text.Json)

2 个答案:

答案 0 :(得分:0)

好的,所以这可能是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属性,如果修复了该错误,并且当我将该类更改回所需的状态时,该属性将继续正常工作。

答案 1 :(得分:0)

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

[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<string,string>属性上使用,这可能是不希望的。对于原始问题中的简单示例,它会很好地工作。