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,将您的 Info 对象添加到集合中,然后将 SetSource(alert) 调用到该 EntitySet。问题就会出现。【参考方案2】:

检查警报类(构造函数

public class Alert
    public Guid AlertIdget;set;
    public List<Info> Infos get;set;

    public Alert() 
        Infos = new List<Info>();
    

看起来您缺少 List init

即使使用 EntitySet

【讨论】:

以上是关于Linq 对象属性在序列化后消失的主要内容,如果未能解决你的问题,请参考以下文章

序列化作用

LINQ 根据指定属性名称对序列进行排序

Json序列化对象后,使用Lombok后属性xAxis大写变成小写xaxis解决方法

ajxa的html和json格式

C#之linq

LINQ to XML概述