我有一个自定义的 JsonConverter,我需要在我的控制器( [FromBody] )中进行序列化。问题是,当我在此属性上嵌套接口时,会重新创建序列化程序,因此会丢失转换器设置。
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));
}
}
到目前为止,我的解决方案是将序列化程序作为一个字段添加到我的转换器中,并在其中使用正确的 serializationSetting 创建它:
public class ItemComponentConverter : JsonConverter
{
private static JsonSerializer mySerializer = JsonSerializer.Create(new JsonSerializerSettings
{
Converters = { new ItemComponentConverter(), },
});
...
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
...
return parameters.ToObject(itemComponentType, **mySerializer**);
}
...
}
它有效,但如果可以的话,我想要一个更好的解决方案。就我的搜索而言,唯一的其他选择是遍历所有对象属性并拥有一个创建对象实例的开关。这个解决方案不是我想要的。有没有办法设置或更改序列化程序?
编辑:
这是一个也适用于第一个实现的对象示例:
{
"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 参数中的序列化程序来解决这个问题。