How to call JsonConvert.DeserializeObject and disable a JsonConverter applied to a base type via [JsonConverter]?(如何调用 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" 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 fiddle.
另一种选择是使用 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
中的选择属性来手动调用参数化构造函数.
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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何调用 JsonConvert.DeserializeObject 并禁用通过 [JsonConverter] 应用于基本类型的 JsonConverter?
基础教程推荐
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01
- c# Math.Sqrt 实现 2022-01-01
- MS Visual Studio .NET 的替代品 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- rabbitmq 的 REST API 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- 如何激活MC67中的红灯 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01