C# 如何将JSON反序列化为IEnumerable<;基本类型>;使用Newtonsoft JSON.NET

C# 如何将JSON反序列化为IEnumerable<;基本类型>;使用Newtonsoft JSON.NET,c#,json.net,C#,Json.net,考虑到这一点: [ { "$id": "1", "$type": "MyAssembly.ClassA, MyAssembly", "Email": "me@here.com", }, { "$id": "2", "$type": "MyAssembly.ClassB, MyAssembly", "Email": "me@here.com", } ] 这些课程: public abstract class BaseClass {

考虑到这一点:

[
  {
    "$id": "1",
    "$type": "MyAssembly.ClassA, MyAssembly",
    "Email": "me@here.com",
  },
  {
    "$id": "2",
    "$type": "MyAssembly.ClassB, MyAssembly",
    "Email": "me@here.com",
  }
]
这些课程:

public abstract class BaseClass
{
    public string Email;
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
如何将JSON反序列化为:

IEnumerable<BaseClass> deserialized;
IEnumerable反序列化;
我不能使用
jsonvert.Deserialize()
,因为它抱怨
BaseClass
是抽象的。

您需要:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
};

string strJson = JsonConvert.SerializeObject(instance, settings);
因此,JSON如下所示:

{
  "$type": "System.Collections.Generic.List`1[[MyAssembly.BaseClass, MyAssembly]], mscorlib",
  "$values": [
    {
      "$id": "1",
      "$type": "MyAssembly.ClassA, MyAssembly",
      "Email": "me@here.com",
    },
    {
      "$id": "2",
      "$type": "MyAssembly.ClassB, MyAssembly",
      "Email": "me@here.com",
    }
  ]
}
然后可以对其进行反序列化:

BaseClass obj = JsonConvert.DeserializeObject<BaseClass>(strJson, settings);
BaseClass obj=JsonConvert.DeserializeObject(strJson,设置);

文档:

您还可以将可枚举项包装在一个类中:

class Wrapper
{
    IEnumerable<BaseClass> classes;
}
类包装器
{
i可数类;
}

然后对其进行序列化和反序列化。

在反序列化时使用以下JsonSerializerSettings构造:

new JsonSerializerSettings()
{
    TypeNameHandling = TypeNameHandling.Objects
})

下面是一种不在json中填充$type的方法

Json转换器:

public class FooConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(BaseFoo));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        if (jo["FooBarBuzz"].Value<string>() == "A")
            return jo.ToObject<AFoo>(serializer);

        if (jo["FooBarBuzz"].Value<string>() == "B")
            return jo.ToObject<BFoo>(serializer);

        return null;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
公共类FooConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回(objectType==typeof(BaseFoo));
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
JObject jo=JObject.Load(读卡器);
如果(jo[“FooBarBuzz”].Value()=“A”)

return jo.ToObject

由于我只需要特定基类的一个侧序列化程序(使API返回派生类属性),所以我提出了当前的解决方案

public class CustomConverter : JsonConverter<BaseClass>
{
    private readonly JsonSerializerOptions _serializerOptions;

    public CustomConverter()
    {
        _serializerOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            IgnoreNullValues = true,
        };
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(BaseClass));
    }

    public override BaseClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(JsonSerializer.SerializeToUtf8Bytes(value, value.GetType(), _serializerOptions));
    }
}
公共类CustomConverter:JsonConverter
{
私有只读JsonSerializerOptions\u serializerOptions;
公共自定义转换器()
{
_serializerOptions=新的JsonSerializerOptions
{
PropertyNamingPolicy=JsonNamingPolicy.CamelCase,
IgnoreNullValues=true,
};
}
公共覆盖布尔CanConvert(类型objectType)
{
返回(objectType==typeof(BaseClass));
}
公共重写基类读取(参考Utf8JsonReader读取器,键入typeToConvert,JsonSerializerOptions选项)
{
抛出新的NotImplementedException();
}
公共重写无效写入(Utf8JsonWriter编写器、基类值、JsonSerializerOptions选项)
{
writer.WriteStringValue(JsonSerializer.SerializeToUtf8Bytes(value,value.GetType(),_serializerOptions));
}
}

我和你有同样的问题,但这对我不起作用(因为我已经在这样做了),当你反序列化它时,它也会抱怨同样的原因。@AndrewBullock你知道
$type
的参数是什么吗?我找到了很多例子,但没有找到解释。为什么你需要指定
MyAssembly.ClassA
,然后再指定
MyAssembly
?链接的
TypeNameHandling
页面没有为这个谜团提供一个解释:(这里的最后一行肯定是不正确的,如果最后一行没有读到
var obj=JsonConvert.DeserializeObject(strJson,settings)
的话,您有一个
列表
,您正试图将其反序列化为
基类
“MyAssembly.ClassB,MyAssembly”
不包含在json中,请使用自定义条件确定要反序列化到另一个条件的派生对象类型?请小心,这会使您的端点面临安全问题:很好的解决方案,但在应用前请阅读此答案非常好,但如果缺少“FooBarBuzz”,则会出错(即,您需要格式一致的json)。您还可以检查字段是否存在,如图所示-
$type
信息应进行安全性清理。有关详细信息,请参阅。
public class CustomConverter : JsonConverter<BaseClass>
{
    private readonly JsonSerializerOptions _serializerOptions;

    public CustomConverter()
    {
        _serializerOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            IgnoreNullValues = true,
        };
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(BaseClass));
    }

    public override BaseClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(JsonSerializer.SerializeToUtf8Bytes(value, value.GetType(), _serializerOptions));
    }
}