本文介绍了如何调用JsonConvert.DeserializeObject并禁用通过[JsonConverter]应用于基本类型的JsonConverter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

澄清问题:

我已经为基本类型重写了JsonConverter(通过对超类应用[JsonConverter(typeof(TConverter))]),但是当直接反序列化子类型时,我想使用STANDARD序列化(即没有自定义转换器)来反序列化我的派生对象.如何在反序列化方法中使用STANDARD序列化,就像我没有重写JsonConverter一样?

I have overridden the JsonConverter for a base type (by applying [JsonConverter(typeof(TConverter))] to the superclass), but when deserializing the sub-type directly I want to use STANDARD serialization (i.e. no custom converter) for deserializing my derived object. How do I specify STANDARD serialization for use in the deserialize method, as if I had NOT overridden the JsonConverter?

我正在使用弹性搜索,无法使用我的JsonConverter的自定义实现调用JsonConvert.DeserializeObject,并且必须依赖Elastic的属性才能使用我的转换器.

I am using elastic search and can't call JsonConvert.DeserializeObject with my custom implementation of JsonConverter, and have to rely on the attribute for Elastic to use my converter.

但是,使用此转换器作为属性似乎也影响所有子类,但我只希望它们使用标准转换器,这样我就不必为许多实现中的每一个实现JsonConverter.

However, using this converter as attribute seems to affect all sub classes as well, but I just want them to use the standard converter, so that I don't have to implement JsonConverter for each of many implementations.

这是我想要的类/逻辑:

This is my classes/logic as I would like it to look:

    [Route("test")]
    [HttpPost]
    public HttpResponseMessage Test([FromBody] JToken json)
    {
        var res = json.ToObject<Product>(); // I want an object of ProductImpl type here
        return Request.CreateResponse(res);
    }

    [JsonConverter(typeof(JsonProductConverted))]
    public abstract class Product
    {
    }

    public class ProductImpl : Product
    {
    }

    public class JsonProductConverted : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject json = JObject.Load(reader);
            //var type = GetTypeFromId((int) json["typeId"]); // Construct type from field in
            var type = typeof(ProductImpl);
            // var res = JsonConvert.DeserializeObject(json.ToString(), type, DEFAULT_JSONCONVERTER_HERE);
            var res = DeserializeToObjectWithStandardJsonConverter(json, type);
            return res;
        }

        public override bool CanConvert(Type objectType)
        {
            return false;
        }
    }

如果我不提供默认的JsonConverter或类似的东西,它将仅使用JsonProductConverted转换器,这将创建一个无限循环.

If I don't supply the default JsonConverter, or similar it will just use the JsonProductConverted converter, which creates an infinite loop.

推荐答案

由于已将[JsonConverter(typeof(JsonProductConverted))]直接添加到Product类型,因此可以在ProductImpl中添加一个虚拟转换器,该转换器将从false href ="http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonConverter_CanRead.htm" rel ="nofollow noreferrer"> CanRead CanWrite :

Since you have added [JsonConverter(typeof(JsonProductConverted))] directly to your Product type, you could add a dummy converter to ProductImpl that returns false from CanRead and CanWrite:

[JsonConverter(typeof(NoConverter))]
public class ProductImpl : Product
{
}

public class NoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return false;
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

这将覆盖基类的转换器,然后回退到用于读取和写入的默认序列化

This overrides the base class's converter and then falls back on default serialization for both reading and writing

示例 .Net小提琴.

另一种选择是使用 serializer.Populate() .这样可以避免调用对象本身的转换器:

Another option would be to use serializer.Populate(). This avoids the call to the converter for the object itself:

public class JsonProductConverted : JsonTypeInferringConverterBase
{
    protected override Type InferType(Type objectType, JObject json)
    {
        //var type = GetTypeFromId((int) json["typeId"]); // Construct type from field in
        return typeof(ProductImpl);
    }

    public override bool CanConvert(Type objectType)
    {
        return false;
    }
}

public abstract class JsonTypeInferringConverterBase : JsonConverter
{
    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    protected abstract Type InferType(Type objectType, JObject json);

    protected virtual object CreateObject(Type actualType, JsonSerializer serializer, JObject json)
    {
        var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(actualType);
        return contract.DefaultCreator();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var json = JObject.Load(reader);

        var actualType = InferType(objectType, json);

        // Construct object (or reuse existingValue if compatible)
        if (existingValue == null || !actualType.IsAssignableFrom(existingValue.GetType()))
        {
            existingValue = CreateObject(actualType, serializer, json);
        }

        // Populate object.
        using (var subReader = json.CreateReader())
        {
            serializer.Populate(subReader, existingValue);
        }

        return existingValue;
    }
}

请注意,具体对象必须具有无参数的构造函数才能起作用.如果没有,您可以覆盖protected virtual object CreateObject(Type actualType, JsonSerializer serializer, JObject json)并通过反序列化JObject json中的select属性来手动调用参数化的构造函数.

Note that the concrete objects must have parameterless constructors for this to work. If not, you can override protected virtual object CreateObject(Type actualType, JsonSerializer serializer, JObject json) and manually invoke a parameterized constructor by deserializing select properties inside the JObject json.

样本小提琴#2 .

这篇关于如何调用JsonConvert.DeserializeObject并禁用通过[JsonConverter]应用于基本类型的JsonConverter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 00:18