Unable to deserialize polymorphic dictionary json due to KnownType "__type" issue
我创建了一个包含多态值的字典,其中保存了一个类对象。我已成功序列化 JSON。但我无法反序列化它。它给出以下错误:
Element ':Value' contains data of the ':Sale' data contract. The deserializer has no knowledge of any type that maps to this contract.
如果将 JSON 属性
我的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; class Program { static void Main(string[] args) { Dictionary<string, object> dict = new Dictionary<string, object>(); dict.Add("employee","john"); dict.Add("sale",new Sale(9,5243)); dict.Add("restaurant",new Restaurant("Cheese Cake Factory","New York")); // Console.Write(dict["sale"]); //Code for JSON DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Dictionary<string, object>)); MemoryStream msObj = new MemoryStream(); js.WriteObject(msObj, dict); msObj.Position = 0; StreamReader sr = new StreamReader(msObj); string json = sr.ReadToEnd(); sr.Close(); msObj.Close(); // Decode the thing Console.Write(json); Dictionary<string, object> result = new Dictionary<string, object>(); using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Dictionary<string, object>)); result = serializer.ReadObject(stream) as Dictionary<string, object>; } } } [DataContract] [KnownType(typeof(Sale))] public class Sale { [DataMember(Name ="SaleId")] public int SaleId {get; set;} [DataMember(Name ="Total")] public int Total{ get; set;} public Sale(int saleid, int total) { SaleId = saleid; Total = total; } public int getTotal() { return Total; } } [DataContract(Name ="Restaurant", Namespace="")] [KnownType(typeof(Restaurant))] public class Restaurant { [DataMember(EmitDefaultValue = false)] public string Name {get; set;} [DataMember(EmitDefaultValue = false)] public string City{get; set;} public Restaurant(string name, string city) { Name = name; City = city; } } |
小提琴链接:https://dotnetfiddle.net/CfQxxV
您正在尝试使用多态成员序列化根对象
那么,如何使用您的数据模型来做到这一点?有几种方法:
将
的答案所示
这不能在这里工作,因为基本类型是
将
这看起来有问题,因为您的根对象类型是
1 2 3 4 5 |
然后使用这个子类构造和序列化你的字典:
1 2 3 4 5 6 7 8 |
这里是演示小提琴#1。
通过使用
中指定
1 2 3 4 5 |
确保为序列化和反序列化以相同的方式配置序列化程序。
这里是演示小提琴#2。
(对于 XML,使用
通过配置文件指定其他已知类型,如添加已知类型的其他方法中所示。
您是直接序列化,但如果您是通过 WCF 进行序列化,则可以将
永远不需要将
1 2 3 4 5 6 | [DataContract] //[KnownType(typeof(Sale))] Remove this public class Sale { // Remainder unchanged } |
有关更多信息,请参阅 Sowmy Srinivasan 的所有关于 KnownTypes。
您遇到的问题是您将
使用 KnownType 的原因是为了在 1 和另一个对象之间进行转换。所以反序列化器不知道
只有当字典中的所有项目都共享一个公共父对象时,这才有效,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | [KnownType(typeof(Sale))] [KnownType(typeof(Restaurant))] [KnownType(typeof(Employee))] [DataContract] public class SomeObject { } [DataContract(Name ="Sale", Namespace="")] public class Sale : SomeObject { //methods + properties + variables } [DataContract(Name ="Restaurant", Namespace="")] public class Restaurant : SomeObject { //methods + properties + variables } [DataContract(Name ="Employee", Namespace="")] public class Employee: SomeObject { //methods + properties + variables } |
然后使用字典作为
1 |