使用 JsonSerializer.DeserializeAsync 反序列化 JSON 没有使用我的 JsonConverter
Deserialising JSON using JsonSerializer.DeserializeAsync is not using my JsonConverter
服务器正在返回一个 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
,因此它尝试自行解析值,并且失败(结果异常是 'invalid cast' 因为它试图 GetEnumerable()
等)。我的转换器中的断点从未被击中。
我可以通过将 属性 设为 object
然后在稍后使用它的地方转换为 Dictionary
来让它工作,但这是一个丑陋的解决方案。
有没有办法强制 JsonSerializer.DeserializeAsync<T>(myJson)
只使用我的转换器,而不是让它自己变得聪明?
(我在 .NET Core 3 中使用微软的 System.Text.Json)
好的,所以这可能是 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);
}
我的反序列化 class 的消费者只需使用 Parameters
属性,如果修复此错误并且我更改 class,它将继续正常工作] 回到我喜欢的样子。
我会创建一个包装器并为该包装器创建一个转换器。
[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>
属性,这可能不是预期的。它适用于原始问题中的简单示例。
服务器正在返回一个 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
,因此它尝试自行解析值,并且失败(结果异常是 'invalid cast' 因为它试图 GetEnumerable()
等)。我的转换器中的断点从未被击中。
我可以通过将 属性 设为 object
然后在稍后使用它的地方转换为 Dictionary
来让它工作,但这是一个丑陋的解决方案。
有没有办法强制 JsonSerializer.DeserializeAsync<T>(myJson)
只使用我的转换器,而不是让它自己变得聪明?
(我在 .NET Core 3 中使用微软的 System.Text.Json)
好的,所以这可能是 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);
}
我的反序列化 class 的消费者只需使用 Parameters
属性,如果修复此错误并且我更改 class,它将继续正常工作] 回到我喜欢的样子。
我会创建一个包装器并为该包装器创建一个转换器。
[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>
属性,这可能不是预期的。它适用于原始问题中的简单示例。