Linq 对象属性在序列化后消失
Posted
技术标签:
【中文标题】Linq 对象属性在序列化后消失【英文标题】:Linq object properties disappear after serialization 【发布时间】:2014-01-13 15:52:49 【问题描述】:我正在尝试了解包含的代码 sn-ps 行为,但它没有按我的预期工作。这是我正在做的事情:
-
将 LINQ 对象序列化为 JSON
将 (1) 处的 JSON 反序列化回其初始类型
验证每个属性是否仍在对象中
我将对象从 (2) 序列化回 JSON
打印 (4) 中的 json 并进行目视检查
我的问题是,在 (5) 处,作为主 LINQ 对象属性的任何 LINQ 实体都消失了,即使在 (3) 处验证时它仍然存在。我所有的 LINQ 类都是 LINQ to SQL。我正在使用牛顿 JSON.Net 库。我用非 linq 对象尝试了相同类型的逻辑,并没有出现 (5) 中看到的缺陷。
var infoId = Guid.NewGuid();
var alertId = Guid.NewGuid();
var info = new Info();
info.InfoId = infoId;
var alert = new Alert();
alert.AlertId = alertId;
alert.Infos.Add(info);
var json = JsonConvert.SerializeObject(alert);
Debug.WriteLine(json); //All looking good, nothing missing
var deserializedObject = JsonConvert.DeserializeObject<Alert>(json);
Assert.AreEqual(alertId, deserializedObject.AlertId); //Assert is valid
Assert.AreEqual(infoId, deserializedObject.Infos[0].InfoId); //Assert is valid
var json2 = JsonConvert.SerializeObject(deserializedObject);
Debug.WriteLine(json2); //Infos is gone
更新:
我已经做了一些调试,并且在反序列化对象的序列化中
var json2 = JsonConvert.SerializeObject(deserializedObject);
我在到达信息序列化步骤时看到以下内容(下一个代码被剪断):
-
this.serializing 是真的
this._Infos.HasLoadedOrAssignedValues 为假
调用get return null。 (get 返回空值)
如果我放置一个断点,并将光标放在返回 this._Infos 上,我实际上会看到它应该返回的对象...
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Alert_Info", Storage="_Infos", ThisKey="AlertId", OtherKey="AlertId")]
[global::System.Runtime.Serialization.DataMemberAttribute(Order=15, EmitDefaultValue=false)]
public EntitySet<Info> Infos
get
if ((this.serializing && (this._Infos.HasLoadedOrAssignedValues == false)))
return null;
return this._Infos;
set
this._Infos.Assign(value);
更新: 这使我相信,当从 Newtons Json.Net 反序列化 HasLoadedOrAssignedValues 的默认值时,我可能需要找到一种方法来修改它。
我还发现了一个肮脏的修复,我不太喜欢它似乎正在工作:
var deserializedObject = JsonConvert.DeserializeObject<EasAlert>(json);
var list = new List<EasInfo>();
deserializedObject.EasInfos.SetSource(list); //<--- Fix, the Info will show up in json2
Assert.AreEqual(alertId, deserializedObject.AlertId);
Assert.AreEqual(infoId, deserializedObject.EasInfos[0].InfoId);
【问题讨论】:
你能告诉我们更多关于你的类是如何构建的吗? 你能看到Debug.WriteLine(json)的所有信息吗? ? 我会为 Infos 使用 List 而不是 Array,因为在 Infos 中知道什么不起作用会更简单。 看起来 Infos 已经是一个列表,不能在数组上调用 Add() 并且 Infos[0] 只是从列表中获取第一项 能否请您包括 Info 和 Alert 的模型定义? 【参考方案1】:我正在尝试 Microsoft 的 javascriptSerializer,它运行良好。代码和输出可以在下面找到。
这可能是牛顿的错误吗?
void Main()
var infoId = Guid.NewGuid();
var alertId = Guid.NewGuid();
var info = new Info();
info.InfoId = infoId;
var alert = new Alert();
alert.AlertId = alertId;
alert.Infos.Add(info);
var jss = new JavaScriptSerializer();
var json = jss.Serialize(alert); //JsonConvert.SerializeObject(alert);
Debug.WriteLine(json); //All looking good, nothing missing
var deserializedObject = jss.Deserialize<Alert>(json); //JsonConvert.DeserializeObject<Alert>(json);
(alertId == deserializedObject.AlertId).Dump(); //Assert is valid
(infoId == deserializedObject.Infos[0].InfoId).Dump(); //Assert is valid
var json2 = jss.Serialize(deserializedObject); //JsonConvert.SerializeObject(deserializedObject);
Debug.WriteLine(json2); //Infos is gone - NOT GONE!
public class Alert
public Guid AlertId get; set;
public List<Info> Infos get; set;
public Alert()
Infos = new List<Info>();
public class Info
public Guid InfoId get; set;
输出:
"AlertId":"0340e855-065c-4ac7-868e-5999fa4b7862","Infos":["InfoId":"31e269a1-4354-423d-84bc-62f6dc06b10f"]
是的
是的
"AlertId":"0340e855-065c-4ac7-868e-5999fa4b7862","Infos":["InfoId":"31e269a1-4354-423d-84bc-62f6dc06b10f"]
【讨论】:
要重现我的错误,您必须使用 Linq to Sql 对象。使用该 linq to Sql 对象,您需要创建一个新的 EntitySet检查警报类(构造函数)
public class Alert
public Guid AlertIdget;set;
public List<Info> Infos get;set;
public Alert()
Infos = new List<Info>();
看起来您缺少 List init
即使使用 EntitySet
【讨论】:
以上是关于Linq 对象属性在序列化后消失的主要内容,如果未能解决你的问题,请参考以下文章