C#将不同接口实现的JSON列表反序列化为一个列表,而不会丢失数据
我能够成功地将包含Employee和Manager对象的混合列表序列化为JSON 但是,当我尝试将JSON反序列化回列表时,我将丢失子类中的所有字段数据,并且当我尝试强制转换到任何一个子类时,我会得到一个空值。如何反序列化这些用户的列表而不丢失Employee和Manager子类字段中的数据C#将不同接口实现的JSON列表反序列化为一个列表,而不会丢失数据,c#,json,deserialization,C#,Json,Deserialization,我能够成功地将包含Employee和Manager对象的混合列表序列化为JSON 但是,当我尝试将JSON反序列化回列表时,我将丢失子类中的所有字段数据,并且当我尝试强制转换到任何一个子类时,我会得到一个空值。如何反序列化这些用户的列表而不丢失Employee和Manager子类字段中的数据 [DataContract] public class User { [DataMember] public string FirstName { get; set; } [DataMember
[DataContract]
public class User {
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
[DataContract]
public class Employee : User {
[DataMember]
public string JobTitle { get; set; }
}
[DataContract]
public class Manager : User {
[DataMember]
public string Department { get; set; }
}
EDIT——这是我的反序列化代码:
// abridged
public void Client() {
var jsonContent = jsonResponse.Content;
var entityList = Deserialize<IEnumerable<T>>(new JsonMediaTypeFormatter(), jsonContent);
}
protected T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class {
// Write the serialized string to a memory stream.
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
// Deserialize to an object of type T
return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
}
//节略
公共无效客户端(){
var jsonContent=jsonResponse.Content;
var entityList=反序列化(新的JsonMediaTypeFormatter(),jsonContent);
}
受保护的T反序列化(MediaTypeFormatter格式化程序,字符串str),其中T:class{
//将序列化字符串写入内存流。
Stream=新的MemoryStream();
StreamWriter writer=新StreamWriter(流);
writer.Write(str);
writer.Flush();
流位置=0;
//反序列化为T类型的对象
返回formatter.ReadFromStreamAsync(typeof(T),stream,null,null)。结果为T;
}
您可以使用DataContractJsonSerializer
和一组作为序列化器构造函数参数传递的已知类型来实现这一点
我创建了一个简单的测试代码来演示:
var list = new List<User>() {
new User { FirstName = "user1", LastName = "user1" },
new Employee { FirstName = "employee1", LastName = "employee1", JobTitle = "employee1" },
new Manager() { FirstName = "manager1", LastName = "manager1", Department = "manager1"}
};
var serializer = new DataContractJsonSerializer(typeof(List<User>), new [] { typeof(Employee), typeof(Manager) });
string json;
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, list);
stream.Position = 0;
using(var reader = new StreamReader(stream))
{
json = reader.ReadToEnd();
}
}
List<User> list2;
using(var stream = new MemoryStream())
{
using(var writer = new StreamWriter(stream))
{
writer.Write(json);
writer.Flush();
stream.Position = 0;
list2 = (List<User>)serializer.ReadObject(stream);
}
}
var list=新列表(){
新用户{FirstName=“user1”,LastName=“user1”},
新员工{FirstName=“employee1”,LastName=“employee1”,JobTitle=“employee1”},
新经理(){FirstName=“manager1”,LastName=“manager1”,Department=“manager1”}
};
var serializer=newdatacontractjsonserializer(typeof(List),new[]{typeof(Employee),typeof(Manager)});
字符串json;
使用(var stream=new MemoryStream())
{
serializer.WriteObject(流,列表);
流位置=0;
使用(变量读取器=新的流读取器(流))
{
json=reader.ReadToEnd();
}
}
清单2;
使用(var stream=new MemoryStream())
{
使用(var writer=新的StreamWriter(流))
{
Write.Write(json);
writer.Flush();
流位置=0;
list2=(List)serializer.ReadObject(stream);
}
}
您可以使用DataContractJsonSerializer
和一组作为序列化器构造函数参数传递的已知类型来实现这一点
我创建了一个简单的测试代码来演示:
var list = new List<User>() {
new User { FirstName = "user1", LastName = "user1" },
new Employee { FirstName = "employee1", LastName = "employee1", JobTitle = "employee1" },
new Manager() { FirstName = "manager1", LastName = "manager1", Department = "manager1"}
};
var serializer = new DataContractJsonSerializer(typeof(List<User>), new [] { typeof(Employee), typeof(Manager) });
string json;
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, list);
stream.Position = 0;
using(var reader = new StreamReader(stream))
{
json = reader.ReadToEnd();
}
}
List<User> list2;
using(var stream = new MemoryStream())
{
using(var writer = new StreamWriter(stream))
{
writer.Write(json);
writer.Flush();
stream.Position = 0;
list2 = (List<User>)serializer.ReadObject(stream);
}
}
var list=新列表(){
新用户{FirstName=“user1”,LastName=“user1”},
新员工{FirstName=“employee1”,LastName=“employee1”,JobTitle=“employee1”},
新经理(){FirstName=“manager1”,LastName=“manager1”,Department=“manager1”}
};
var serializer=newdatacontractjsonserializer(typeof(List),new[]{typeof(Employee),typeof(Manager)});
字符串json;
使用(var stream=new MemoryStream())
{
serializer.WriteObject(流,列表);
流位置=0;
使用(变量读取器=新的流读取器(流))
{
json=reader.ReadToEnd();
}
}
清单2;
使用(var stream=new MemoryStream())
{
使用(var writer=新的StreamWriter(流))
{
Write.Write(json);
writer.Flush();
流位置=0;
list2=(List)serializer.ReadObject(stream);
}
}
刚刚编辑了原始帖子。看起来像是JsonMediaTypeFormatter吧?您能推荐一个更好的吗?编辑以添加适当的DataContract/DataMember属性。我在我的实际代码中也使用了这些。刚刚编辑了原始文章。看起来像是JsonMediaTypeFormatter吧?您能推荐一个更好的吗?编辑以添加适当的DataContract/DataMember属性。我也在我的实际代码中使用它们。谢谢这个示例!如果我希望整个事情都是动态的,而我不知道实现类可能是什么呢?那么我认为这是不可能的。序列化程序必须搜索所有可用的名称空间,并查找继承您的User
类的任何类。你可以自己编写这部分(使用反射)并将找到的所有内容传递到构造函数中,但我认为这不是真正有效的代码。好的,谢谢你的帮助。我试图从API客户机的角度来考虑这一点。我将返回同一列表中相同接口的这些不同实现的列表。这是一个坏习惯吗?对于不同的实现类型,人们通常会有不同的资源URL吗?这种方法的缺点似乎是,类型字段与其余数据一起序列化到JSON中。我不确定是否要将该信息公开给API客户机…感谢您提供此示例!如果我希望整个事情都是动态的,而我不知道实现类可能是什么呢?那么我认为这是不可能的。序列化程序必须搜索所有可用的名称空间,并查找继承您的User
类的任何类。你可以自己编写这部分(使用反射)并将找到的所有内容传递到构造函数中,但我认为这不是真正有效的代码。好的,谢谢你的帮助。我试图从API客户机的角度来考虑这一点。我将返回同一列表中相同接口的这些不同实现的列表。这是一个坏习惯吗?对于不同的实现类型,人们通常会有不同的资源URL吗?这种方法的缺点似乎是,类型字段与其余数据一起序列化到JSON中。我不确定是否要将该信息公开给API客户端。。。