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));
}
}