C# 具有嵌套接口的自定义JsonConverter

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

我有一个自定义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"
    }
}

第二个示例的情况是,当序列化程序尝试解析类型“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"
    }
}