У меня есть собственный 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));
}
}
Мое решение до сих пор заключается в добавлении сериализатора как поля в моем конвертере, где я создаю его с правильной сериализацией. Решение, если это вариант. Что касается моего поиска, единственным другим вариантом было перебирать все свойства объекта и иметь переключатель, который создает экземпляр объекта. Это решение не то, что я ищу. Есть ли способ установить или изменить сериализатор?
РЕДАКТИРОВАТЬ:
Это пример объекта, который также работает с первой реализацией:
{
"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"
}
}
Что происходит со вторым примером, так это то, что когда сериализатор пытается определить тип «и», он будет вызывать второй раз, а затем третий разМетод ReadJson для десериализации типов «равно» и «в», которые являются частью одного и того же объекта. Все эти три типа IItemComponent . Вторая реализация решает эту проблему, используя статический сериализатор вместо параметра в параметрах ReadJson.