C# 具有嵌套接口的自定义JsonConverter
我有一个自定义JsonConverter,我需要它在我的控制器([FromBody])中进行序列化。问题是,当我在此属性上有嵌套接口时,将重新创建序列化程序,因此转换器设置将丢失C# 具有嵌套接口的自定义JsonConverter,c#,json.net,jsonconverter,C#,Json.net,Jsonconverter,我有一个自定义JsonConverter,我需要它在我的控制器([FromBody])中进行序列化。问题是,当我在此属性上有嵌套接口时,将重新创建序列化程序,因此转换器设置将丢失 public class ItemController { public async Task<IActionResult> PostItem([FromBody] Item item) { var itemDocument = await this.itemReposito
public class ItemController
{
public async Task<IActionResult> PostItem([FromBody] Item item)
{
var itemDocument = await this.itemRepository.CreateItemAsync(item);
return Ok(itemDocument);
}
}
public class Item
{
[JsonProperty("itemComponent", NullValueHandling = NullValueHandling.Ignore)]
**[JsonConverter(typeof(ItemComponentConverter))]**
public IItemComponent ItemComponent { get; internal set; }
}
public class ItemComponentConverter : JsonConverter
{
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType == typeof(IItemComponent);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject parameters = JToken.ReadFrom(reader) as JObject;
if (parameters?["$type"] == null)
{
return null;
}
string itemComponentName = parameters["$type"].Value<string>();
if (!KnownItemComponents.TryGetKnownComponentType(itemComponentName, out Type itemComponentType))
{
return null;
}
return parameters.ToObject(itemComponentType, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException("Cannot write from " + nameof(ItemComponentConverter));
}
}
这是可行的,但如果这是一个选择,我希望有一个更好的解决方案。就我的搜索而言,唯一的另一个选择是迭代所有对象属性,并使用一个开关来创建对象的实例。这个解决方案不是我想要的。有没有办法设置或更改序列化程序
编辑:
这是与第一个实现一起工作的对象示例:
{
"key": "612f8544-8489-4571-86b4-118aedb95575",
"name": "TestItem",
"component": {
"ContextKey": "TestKey1",
"Lhs": "1234",
"$type": "and"
}
}
这是第一个实现不起作用的示例。这就是我所说的嵌套接口:
{
"key": "612f8544-8489-4571-86b4-118aedb95575",
"name": "TestItem",
"component": {
"Left": {
"ContextKey": "TestKey1",
"Lhs": "1234",
"$type": "equals"
},
"Right": {
"ContextKey": "TestKey2",
"Collection": ["joe", "mark"],
"$type": "in"
},
"$type": "and"
}
}
第二个示例的情况是,当序列化程序尝试解析类型“and”时,它将第二次、第三次调用ReadJson方法来反序列化属于同一对象的类型“equals”和“in”。这三种类型都是IItemComponent。第二个实现是通过使用静态序列化程序而不是ReadJson参数中的序列化程序来解决这个问题。我不完全确定我是否理解这个问题。只要
KnownItemComponents.TryGetKnownComponentType(itemComponentName,out-Type itemComponentType)
返回最终的具体类型,为什么需要任何类型的转换器嵌套?你能把你的问题分享给我吗?我添加了两个我正试图反序列化的对象示例。问题是找不到类型。类型解析正确。问题是当您有一个嵌套对象,其子组件具有相同的接口类型时。因此,问题是您已将转换器[JsonConverter(typeof(ItemComponentConverter))]
添加到属性public IItemComponent ItemComponent{get;internal set;}
--但不适用于类型为IItemComponent
的其他属性?为什么不将转换器添加到其他属性?或者全局注册转换器,如中所示。(具体方法取决于您的asp.net版本。)我不能使用JsonConvert.SerializeObject
,因为序列化是在后台使用[FromBody]Item Item
进行的,使用的是作为属性给定的转换器。因为我有一个项目作为参数,所以当我可以访问该对象时已经太迟了,因为它已经尝试反序列化它。因此,在这种情况下,全局设置它将不起作用,任何使用对象本身作为参数的操作,如JsonConvert.SerializeObject
。对于后者,我需要[FromBody]字符串/JObject项,这是我不想要的。但无论如何,谢谢你的投入!
{
"key": "612f8544-8489-4571-86b4-118aedb95575",
"name": "TestItem",
"component": {
"Left": {
"ContextKey": "TestKey1",
"Lhs": "1234",
"$type": "equals"
},
"Right": {
"ContextKey": "TestKey2",
"Collection": ["joe", "mark"],
"$type": "in"
},
"$type": "and"
}
}