gpt4 book ai didi

c# - 使用 DataContractJsonSerializer 将 JSON 反序列化为抽象列表

转载 作者:太空狗 更新时间:2023-10-29 17:48:47 29 4
gpt4 key购买 nike

我正在尝试将 JSON 文件反序列化为包含抽象列表的类的实例。将实例序列化为 Json 效果很好(检查下面的 json 文件)。反序列化时,我收到“System.MemberAccessException”消息“无法创建抽象类”。显然,反序列化器正在尝试实例化抽象类而不是具体类。

在我的示例中,反序列化类称为 ElementContainer:

namespace Data
{
[DataContract]
[KnownType(typeof(ElementA))]
[KnownType(typeof(ElementB))]
public class ElementContainer
{
[DataMember]
public List<Element> Elements { get; set; }
}

[DataContract]
public abstract class Element
{
}

[DataContract]
public class ElementA : Element
{
[DataMember]
int Id { get; set; }
}

[DataContract]
public class ElementB : Element
{
[DataMember]
string Name { get; set; }
}
}

这是已序列化的 Json 文件,我正在尝试反序列化。注意反序列化器的“__type”字段以创建具体类:

{
"Elements":
[
{
"__type":"ElementA:#Data",
"Id":1
},
{
"__type":"ElementB:#Data",
"Name":"MyName"
}
]
}

以下是我用于反序列化的代码:

    public T LoadFromJSON<T>(string filePath)
{
try
{
using (FileStream stream = File.OpenRead(filePath))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
T contract = (T)serializer.ReadObject(stream);
return contract;
}
}
catch (System.Exception ex)
{
logger.Error("Cannot deserialize json " + filePath, ex);
throw;
}
}

有可能使反序列化工作吗?

谢谢!

最佳答案

我们找到了它不起作用的原因。在对象序列化之后,我们识别结果字符串以提高可读性。然后我们将字符串写入文件:

    public void SaveContractToJSON<T>(T contract, string filePath)
{
using (MemoryStream stream = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
serializer.WriteObject(stream, contract);
string json = Encoding.UTF8.GetString(stream.ToArray());
File.WriteAllText(filePath, json.IndentJSON());
}
}

标识实际上是反序列化不起作用的原因。似乎 DataContractJsonSerializer 的解析器真的很挑剔。如果字符 { 和字段“__type”之间有一些字符,序列化程序会丢失。

例如这个字符串将正确序列化:

"{\"Elements\":[{\"__type\":\"ElementA:#Data\",\"Id\":1}]}"

但是下一个字符串不会序列化。

"{\"Elements\":[   {\"__type\":\"ElementA:#Data\",\"Id\":1}]}"

唯一的区别是“__type”之前的空格字符。序列化将抛出 MemberAccessException。这是一种误导,因为只有在反序列化为抽象列表时才会出现此行为。无论字符如何,序列化到抽象字段都可以正常工作。

要在不删除文件可读性的情况下解决此问题,可以在反序列化之前修改字符串。例如:

    public T LoadContractFromJSON<T>(string filePath)
{
try
{
string text = File.ReadAllText(filePath);
text = Regex.Replace(text, "\\{[\\n\\r ]*\"__type", "{\"__type");
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(text)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
T contract = (T)serializer.ReadObject(stream);
return contract;
}
}
catch (System.Exception ex)
{
logger.Error("Cannot deserialize json " + filePath, ex);
throw;
}
}

关于c# - 使用 DataContractJsonSerializer 将 JSON 反序列化为抽象列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3971271/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com