C# 反序列化子类中的匿名顶级数组

C# 反序列化子类中的匿名顶级数组,c#,json,json.net,C#,Json,Json.net,我得到了一个JSON响应,它包含在一个外部数组中,如下所示: [ { "type": "a" }, { "type": "b", "id": 1 }, { "type": "c", "name": "somename" } ] class LoginOptions { public IList<ILoginOption> Options { get; set; } } interface ILoginOpti

我得到了一个JSON响应,它包含在一个外部数组中,如下所示:

[
  {
    "type": "a"
  },
  {
    "type": "b",
    "id": 1
  },
  {
    "type": "c",
    "name": "somename"
  }
]
class LoginOptions
{
    public IList<ILoginOption> Options { get; set; }
}

interface ILoginOption
{
    [JsonProperty("type")]
    LoginType LoginType { get; }
}

class LoginOptionA : ILoginOption{
    public LoginType LoginType
    {
        get { return LoginType.A; }
    }
}

class LoginOptionB : ILoginOption{
    public LoginType LoginType
    {
        get { return LoginType.B; }
    }

    [JsonProperty("id")]
    public int Id { get; set; }
}

class LoginOptionC : ILoginOption{
    public LoginType LoginType
    {
        get { return LoginType.C; }
    }

    [JsonProperty("name")]
    public string Name { get; set; }
}
internal class LoginOptionConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ILoginOption);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var item = JObject.Load(reader);
        var data = item["type"].Value<string>();

        if (data == "UsernamePassword")
        {
            return item.ToObject<LoginOptionA>();
        }

        if (data == "Saml")
        {
            return item.ToObject<LoginOptionB>();
        }

        if (data == "Crm")
        {
            return item.ToObject<LoginOptionC>();
        }

        throw new ArgumentException("Invalid JSON response");
    }
}
我尝试将其转换为如下对象:

[
  {
    "type": "a"
  },
  {
    "type": "b",
    "id": 1
  },
  {
    "type": "c",
    "name": "somename"
  }
]
class LoginOptions
{
    public IList<ILoginOption> Options { get; set; }
}

interface ILoginOption
{
    [JsonProperty("type")]
    LoginType LoginType { get; }
}

class LoginOptionA : ILoginOption{
    public LoginType LoginType
    {
        get { return LoginType.A; }
    }
}

class LoginOptionB : ILoginOption{
    public LoginType LoginType
    {
        get { return LoginType.B; }
    }

    [JsonProperty("id")]
    public int Id { get; set; }
}

class LoginOptionC : ILoginOption{
    public LoginType LoginType
    {
        get { return LoginType.C; }
    }

    [JsonProperty("name")]
    public string Name { get; set; }
}
internal class LoginOptionConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ILoginOption);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var item = JObject.Load(reader);
        var data = item["type"].Value<string>();

        if (data == "UsernamePassword")
        {
            return item.ToObject<LoginOptionA>();
        }

        if (data == "Saml")
        {
            return item.ToObject<LoginOptionB>();
        }

        if (data == "Crm")
        {
            return item.ToObject<LoginOptionC>();
        }

        throw new ArgumentException("Invalid JSON response");
    }
}
我的呼叫调度器将JSON解析为:

private List<ILoginOption> DeserializeObject<List<ILoginOption>>(Stream stream)
{
   using (StreamReader sr = new StreamReader(stream))
   using (JsonReader reader = new JsonTextReader(sr))
   {
       return new JsonSerializer().Deserialize<List<ILoginOption>>(reader);
   }
}
正如所建议的那样,这没有什么区别

请注意,在自定义转换器内部出现此错误之前会引发此错误:创建
JsonSerializer
时会引发此错误

实例化发生在以下位置:

var settings = new JsonSerializerSettings
{
     TypeNameHandling = TypeNameHandling.Objects
};

using (StreamReader sr = new StreamReader(stream))
using (JsonReader reader = new JsonTextReader(sr))
{
    return JsonSerializer.Create(settings).Deserialize<List<ILoginOption>>(reader);
}
var设置=新的JsonSerializerSettings
{
TypeNameHandling=TypeNameHandling.Objects
};
使用(StreamReader sr=新StreamReader(stream))
使用(JsonReader=newjsontextreader(sr))
{
返回JsonSerializer.Create(设置)。反序列化(读取器);
}

由于JSON中的顶层是一个数组,因此应该直接反序列化到列表。不需要包装器类来保存列表

List<ILoginOption> loginOptions = 
                   JsonConvert.DeserializeObject<List<ILoginOption>>(json);
列表登录选项=
反序列化对象(json);

现在,由于您的列表将包含几种不同类型的
ILoginObjects
,Json.Net在反序列化列表时将不知道要创建哪些对象。为此,您需要一个
JsonConverter
。显示如何创建转换器来处理此问题。

我已更改了代码,以便可以使用集合调用反序列化过程,并将其移动到实际对象中。但这仍然会导致错误(请参见编辑问题)。我忘了什么吗?好吧,我设法克服了。根据需要,您必须通过
serializer.Converters.add添加转换器,而不是使用属性。这只会导致我有一个单一的登录选项(第一个),而不是所有的3个。看起来我的问题的本质是我瞄准了一个错误的环境,结果只有一个选择。