我需要对下面给出的Json数组进行反序列化...。
[
{
"GeoType": 1,
"ID": "2650f7d2-7a5e-4b63-856c-07600fa2a854",
"Name": "Afghanistan",
"CapitalCity": null,
"CountryBoundaries": null,
"CountryCode": "AF",
"ISO": "AFG",
"Parent": {
"__type": "Region:#MEDEX.Library.Geo",
"GeoType": 0,
"ID": "6dc22edb-d711-4253-937f-242b0cd3c011",
"Name": "Asia",
"Code": "Asi"
},
"RegionID": "6dc22edb-d711-4253-937f-242b0cd3c011"
},
{
"GeoType": 1,
"ID": "3917c1c8-ee01-4e9b-8622-0fac9e9194ab",
"Name": "Albania",
"CapitalCity": null,
"CountryBoundaries": null,
"CountryCode": "AL",
"ISO": "ALB",
"Parent": {
"__type": "Region:#MEDEX.Library.Geo",
"GeoType": 0,
"ID": "b7ebd500-45e6-4a48-a2ef-f38fe99e7352",
"Name": "Europe",
"Code": "Eur"
},
"RegionID": "b7ebd500-45e6-4a48-a2ef-f38fe99e7352"
}
]
我的对象定义是:
[DataContract]
public class Parent1
{
[DataMember]
public Dictionary<string, Type> __type { get; set; }
[DataMember]
public string ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string GeoType { get; set; }
[DataMember]
public string Code { get; set; }
}
[DataContract]
public class Country
{
[DataMember]
public string ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string GeoType { get; set; }
[DataMember]
public Parent1 Parent { get; set; }
[DataMember]
public string RegionID { get; set; }
[DataMember]
public string CountryCode { get; set; }
[DataMember]
public string ISO { get; set; }
}
总是出错:
{“ Element':Parent'包含映射到名称'http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo:Region'的类型的数据。解串器不知道任何映射到该名称的类型。如果使用,请考虑使用DataContractResolver DataContractSerializer或将与“ Region”相对应的类型添加到已知类型的列表中,例如,通过使用KnownTypeAttribute属性或将其添加到传递给序列化器的已知类型的列表中。“}
您能建议我任何解决方案吗?我什至不明白此错误的含义。请提出建议。
答案 0 :(得分:0)
将[KnownType(Region)]添加到class Parent1属性中
答案 1 :(得分:0)
如this answer至 parse.com: SerializationException deserializing JSON objects with "__type" property 中所述,您的问题是"__type"
是{{1 }}。它用于标识多态类型的派生类型。来自docs:
保留类型信息
要保留类型标识,当将复杂类型序列化为JSON时,可以添加“类型提示”,并且反序列化器会识别该提示并采取适当的措施。 “类型提示”是密钥名称为“ __type”的JSON键/值对(两个下划线,后跟单词“ type”)。该值是格式为“ DataContractName:DataContractNamespace”的JSON字符串(名称中第一个冒号之前的任何内容)...
类型提示与XML Schema Instance标准定义的xsi:type属性非常相似,并在对XML进行序列化/反序列化时使用。
由于与类型提示的潜在冲突,因此禁止使用名为“ __type”的数据成员。
因此,您不能手动将此属性添加到您的类中,并使其正确翻译。
但是,您可以通过定义DataContractJsonSerializer
类继承的区域的类层次结构,利用序列化程序对多态性的处理来自动读写"__type"
Region
所引用的某种基本类型,例如RegionBase
:
Country.Parent
然后将其反序列化为[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
public class Country
{
[DataMember]
public string ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string GeoType { get; set; }
[DataMember]
public RegionBase Parent { get; set; }
[DataMember]
public string RegionID { get; set; }
[DataMember]
public string CountryCode { get; set; }
[DataMember]
public string ISO { get; set; }
}
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
[KnownType(typeof(Region))]
public class RegionBase
{
}
[DataContract(
Name = "Region",
Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
public class Region : RegionBase
{
[DataMember]
public string ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string GeoType { get; set; }
[DataMember]
public string Code { get; set; }
}
,因为您的外部JSON容器是一个数组。
注意:
类型提示的格式为List<Country>
。
此外,如Reducing the Size of Type Hints中所述,类型提示中的前缀"DataContractName:DataContractNamespace"
是#
的快捷方式。因此http://schemas.datacontract.org/2004/07/
必须具有以下数据协定名称:
Region
我的答案中的类型层次结构足以反序列化示例JSON,但可能并不理想。例如,实际上,可能还有[DataContract(
Name = "Region",
Namespace = "http://schemas.datacontract.org/2004/07/MEDEX.Library.Geo")]
的其他子类型与RegionBase
共享属性(例如Region
),因此这些属性应移至基类。或者您的问题中可能没有显示ID
的其他可能子类,例如RegionBase
,需要将其添加到模型中。
由于该JSON似乎来自WCF服务,因此希望它已经发布了Service Metadata。如果是这样,它将允许您使用Visual Studio中的添加服务引用自动自动生成客户端。有关如何执行此操作的说明,请参见How to: Create a Windows Communication Foundation Client和How to: Add, Update, or Remove a Service Reference。自动生成客户端应避免遇到麻烦。
有关此示例,请参见 How to deserialize JSON with unnamed collection of types using DataContractSerializer 或 How to use a WSDL file to create a WCF service (not make a call) 。
必须通过Known Type mechanism将所有"SomeOtherKindOfRegion:#MEDEX.Library.Geo"
的可能多态子类型通知给数据协定序列化程序。