一尘不染

使用JsonConverter的Json.NET自定义序列化-如何获得“默认”行为

json

我的类DataType有一个JsonConverter。当在Json中使用纯字符串作为DataType类型的属性的值时,我想做一些特殊的处理。在值是“完整”对象的情况下,我想进行“常规”反序列化。

这是我的尝试

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.Value != null && reader.ValueType == typeof (string))
    {
        return someSpecialDataTypeInstance;
    }
    else if (reader.TokenType == JsonToken.StartObject)
    {
        DataType dataType = serializer.Deserialize<DataType>(reader);
        return dataType;
    }
    else
    {
        throw new JsonSerializationException();
    }
}

但这不起作用,因为这行:DataType dataType = serializer.Deserialize(reader); 导致无限递归。

可以通过某种方式轻松完成吗?(无需手动逐个属性)


阅读 203

收藏
2020-07-27

共1个答案

一尘不染

一种简单的方法是分配您的类的实例,然后使用JsonSerializer.Populate(JsonReader, Object)。这是在标准中完成的方式CustomCreationConverter<T>

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.Value != null && reader.ValueType == typeof(string))
    {
        return someSpecialDataTypeInstance;
    }
    else if (reader.TokenType == JsonToken.StartObject)
    {
        existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        serializer.Populate(reader, existingValue);
        return existingValue;
    }
    else if (reader.TokenType == JsonToken.Null)
    {
        return null;
    }
    else
    {
        throw new JsonSerializationException();
    }
}

局限性:

  • 如果TypeNameHandling启用了"$type"该功能,并且存在指定多态子类型的属性,则无法处理这种情况。

在这种情况下,你需要做一些招数利用通过 JsonDerivedTypeConverer<T>
JsonConverter与接口

  • 要反序列化的类型必须具有Json.NET可访问的无参数构造函数。如果不是,并且existingValue为null,则必须通过手动进行构造new DataType(arg1, arg2, ...)

  • PreserveReferencesHandling不支持引用保存。

有关处理这种情况的一种方法,请参见
如何根据json的结构选择要在运行时反序列化的类型?

样品提琴

2020-07-27