首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调用JsonConvert.DeserializeObject并禁用通过[ JsonConverter ]应用于基类型的JsonConverter?

如何调用JsonConvert.DeserializeObject并禁用通过[ JsonConverter ]应用于基类型的JsonConverter?
EN

Stack Overflow用户
提问于 2017-08-07 12:38:19
回答 1查看 3K关注 0票数 2

编辑:澄清问题:

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

我使用弹性搜索,不能用自定义的JsonConverter实现来调用JsonConverter,并且必须依赖于弹性的属性来使用我的转换器。

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

这是我想要看到的类/逻辑:

代码语言:javascript
复制
    [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转换器,这将创建一个无限循环。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-07 19:05:30

因为您已经将[JsonConverter(typeof(JsonProductConverted))]直接添加到Product类型中,所以可以向ProductImpl添加虚拟转换器,从CanReadCanWrite返回false

代码语言:javascript
复制
[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();
    }
}

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

样品.Net小提琴.

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

代码语言:javascript
复制
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属性来手动调用参数化构造函数。

样品小提琴#2.

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45547123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档