如何将一个项目反序列化为不同的类型? (Newtonsoft、C#、.NET)

How to deserialize an item into different types? (Newtonsoft, C#, .NET)

我收到一条 json 消息,其中包含一个名为 "item" 的字段,可以将其反序列化为 class foo 或 class bar。 我如何在 C# 中实现它?

我假设是这样的:

public class FooOrBar 
{
     // Only one of the two will get populated.
     public Foo foo { get; set; }
     public Bar bar { get; set; }
     bool is_foo;
}

[JsonProperty("item")]
[JsonConverter(typeof(CustomConverter))]
public FooOrBar Item { get; set; }

如何为这种情况实现自定义转换器?

有没有更简单的解决方案?

我不确定 FooBar 是如何在您的代码中确定的,但现在让我们假设您有一个像这样的 JSON 结构:

var json = @"
{
  isFoo: true,
  item: {}
}";

在这种情况下 FooBarisFoo 决定。

FooOrBar class 可能是主观的。我不会那样定义 class,而是使用多态性:

interface IItem
{
    bool IsFoo { get; }
}

class Foo : IItem
{
    public bool IsFoo => true;
}

class Bar : IItem
{
    public bool IsFoo => false;
}

[JsonConverter(typeof(CustomJsonConverter))]
class MyClass
{
    public IItem Item { get; set; }
}

我将 CustomJsonConverter 设置为 MyClass 因为我有 JSON 结构。我需要使用 item 的父对象中可用的信息来确定 FooBar,因此我必须将 JsonConverter 设置为 Item 的声明类型 属性。如果您使用 item 属性 中可用的信息,您可以将转换器移动到 Item 属性.

现在像这样实现 CustomJsonConverter

class CustomJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override object ReadJson(JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        var token = JToken.ReadFrom(reader);
        if (token.Type == JTokenType.Null)
        {
            return null;
        }

        // Create an instance of MyClass, and set property as per "isFoo".
        var obj = new MyClass();        

        if (token["isFoo"].Value<bool>())
        {
            obj.Item = new Foo();
        }
        else
        {
            obj.Item = new Bar();
        }

        // Populate properties
        serializer.Populate(token.CreateReader(), obj);
        return obj;
    }

    public override void WriteJson(JsonWriter writer, object value, 
        JsonSerializer serializer)
    {
        throw new NotSupportedException();
    }
}