Json.NET 自定义序列化与 JsonConverter - 如何获得“默认"行为 [英] Json.NET custom serialization with JsonConverter - how to get the "default" behavior

查看:18
本文介绍了Json.NET 自定义序列化与 JsonConverter - 如何获得“默认"行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a JsonConverter for my class DataType. I would like to do some special handling when plain string used in Json as the value of a property of type DataType. In the case where the value is a "full" object, I would like to do the "normal" deserialization.

这是我的尝试

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);导致无限递归.

But this doesn't work, because this line: DataType dataType = serializer.Deserialize(reader); causes infinite recursion.

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

Could this be done somehow easily? (without the need to manually go property-by-property)

推荐答案

一种简单的方法是分配一个类的实例,然后使用 JsonSerializer.Populate(JsonReader, Object).这是在标准 CustomCreationConverter:

One easy way to do it is to allocate an instance of your class then use JsonSerializer.Populate(JsonReader, Object). This is the way it is done in the standard 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" 属性.

在这种情况下,您需要在 带接口的 JsonConverter.

In this case you'll need to do some of the tricks use by JsonDerivedTypeConverer<T> in JsonConverter with Interface.

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

The type to be deserialized must have a parameterless constructor accessible to Json.NET. If not, and existingValue is null, it will be necessary to construct it manually, via new DataType(arg1, arg2, ...).

参考保存通过 PreserveReferencesHandling 不受支持.

Reference preservation via PreserveReferencesHandling is not supported.

有关处理这种情况的一种方法,请参阅如何根据json?.

For one approach to handle this situation see How can I choose what type to deserialize at runtime based on the structure of the json?.

示例 fiddle.

这篇关于Json.NET 自定义序列化与 JsonConverter - 如何获得“默认"行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆