当前位置: 首页 > 面试题库 >

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

乔凯康
2023-03-14
问题内容

编辑:澄清问题:

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

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

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

这是我希望看到的类/逻辑

    [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转换器,这将创建一个无限循环。


问题答案:

既然你已经添加[JsonConverter(typeof(JsonProductConverted))]直接到你的Product类型,你可以一个虚拟的转换器添加到ProductImpl该收益false来自CanReadCanWrite

[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()。这样可以避免调用对象本身的转换器:

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)通过反序列化内的select属性来覆盖并手动调用参数化的构造函数JObject json

样本小提琴2。



 类似资料:
  • 我正在制作一个Java类,在这个类中,我可以用DTO对列表应用一个过滤器(searchterms)。筛选器如下所示: 在我的类中,我有以下方法,将所有筛选器应用到列表: 但是根据字段的类型有不同的实现。与字符串类似,我创建了一个正则表达式: 但就像一个Float我想要另一个比较,我不想应用正则表达式到一个Float。要确保根据字段的类型调用正确的方法,最好的方法是什么?

  • 问题内容: 我正在用Java编写一个Kafka流应用程序,该应用程序将接受由连接器创建的输入主题,该连接器将模式注册表和avro用于键和值转换器。连接器产生以下架构: 实际上,有几个主题,键模式始终是“ int”,而值模式始终是某种记录(用户,产品等)。我的代码包含以下定义 最初,我尝试使用类似的内容来使用该主题, Consumed.with(Serdes.Integer(), userSerde

  • 英文原文:http://emberjs.cn/guides/configuring-ember/disabling-prototype-extensions/ 默认情况下,Ember.js 以下列方式对原生的JavaScript对象进行基于原型的扩展: Array被扩展用来实现Ember.Enumerable, Ember.MutableEnumerable, Ember.MutableArray

  • 我一直听说确保最佳性能的最佳实践是: 按值传递基本类型(,..) 通过常量引用传递类 如今,在编译器下使用C 11和完全优化,当通过const引用传递基本类型时是否会产生开销? 此外,当<code>T<code>为<code>int<code>时,将执行以下功能: 慢于:

  • 问题内容: 如何在Django 1.3中使用分页? 该文档对此不是很清楚。 我views.py怎么了? 我的模板如何处理? URLconf文件中有什么内容? 问题答案: 我认为你需要有关将分页与基于新类的视图一起使用的信息,因为使用基于传统函数的视图很容易找到。我发现仅通过设置变量就足以激活分页。请参见基于类的通用视图。 例如,在你的: 在你的模板(),你可以包括这样的分页部分(我们有一些情境变量

  • 问题内容: 我有一个使用laravel用PHP编写的Web应用程序。 现在,我必须添加实时通知系统,该系统可以从服务器->客户端推送消息,并且可以检索从客户端->服务器推送的消息。 由于Socket.IO向后兼容且性能下降,因此我想将其用于WebSocket / AJAX轮询部分。 问题是默认情况下Socket.IO可与Node.JS后端一起使用。 我具有对服务器的root访问权限,并行运行(Ap