Json.Net - 将 JSON 反序列化为字典,并对特定字段进行特殊处理



https://dotnetfiddle.net/ka6XVw - 摆弄示例类型结构

假设我有一个实现IDictionary<string, T> 的类。 Json.Net 可以开箱即用地反序列化此类类型,创建该类型的实例并使用其索引器填充字典。问题是这个类还从它的基类继承了一个标有JsonProperty属性的字符串Error属性,我希望每当输入 json 包含error字段时填充此属性。但是,在反序列化IDictionary Json.Net 时,将所有字段视为字典条目,并尝试将带有 error 键的值添加到字典中。

将 json 反序列化为字典并将error字段反序列化为 Error 属性的最简单、最干净的方法是什么?请注意,该类是泛型的,因此JsonExtensionData不是一个选项(不将其值转换为提供的类型(。

示例有效字典 json:{ 'foo': '1', 'bar': '2' }

示例错误 json { 'error': 'blah' }

我从这个问题中得出了一个转换器解决方案。基本上,您将转换器附加到DictionaryResponse类,并自己解释传入的 JSON。我懒得用JObject解析:

class DictionaryResponseConverter : JsonConverter<ResponseBase>
{
    public override ResponseBase ReadJson(
        JsonReader reader, Type objectType,
        ResponseBase existingValue, bool hasExistingValue,
        JsonSerializer serializer)
    {
        // find the correct T and call the internal function through reflection
        // as DictionaryResponse<T> is sealed, we don't care about inheritance
        return (ResponseBase)GetType()
            .GetMethod(nameof(InternalReadJson),
                       BindingFlags.Instance | BindingFlags.NonPublic)
            .MakeGenericMethod(objectType.GetGenericArguments()[0])
            .Invoke(this, new object[]
            {
                reader,
                existingValue,
                hasExistingValue,
                serializer
            });
    }
    DictionaryResponse<T> InternalReadJson<T>(
        JsonReader reader,
        DictionaryResponse<T> existingValue, bool hasExistingValue,
        JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var obj = JObject.Load(reader);
        var error = (string)obj["error"];
        bool hadError = obj.Remove("error");
        //var result = new DictionaryResponse<T>();
        var result = hasExistingValue ? existingValue : new DictionaryResponse<T>();
        foreach (var kvp in obj)
            result[kvp.Key] = kvp.Value.ToObject<T>();
        if (hadError)
            result.Error = error;
        return result;
    }
    public override void WriteJson(
        JsonWriter writer, ResponseBase value, JsonSerializer serializer)
    {
        // don't care about serialization
        throw new NotImplementedException();
    }
}
[JsonConverter(typeof(DictionaryResponseConverter))]
internal sealed class DictionaryResponse<T> : ResponseBase, IDictionary<string, T>
{
    ...

相关内容

  • 没有找到相关文章

最新更新