编程语言
首页 > 编程语言> > c#-使用JsonConvert进行序列化会丢失数据

c#-使用JsonConvert进行序列化会丢失数据

作者:互联网

这个问题已经在这里有了答案:            >            Json.net serialize/deserialize derived types?                                    3个
我在项目中使用JsonConvert以便从对象创建json字符串,但是发生了一些奇怪的事情,其中​​一个实体在过程中丢失了数据,这很奇怪,因为在调试时,该实体具有值,但是由于某种原因,它会在此过程中丢失.

我使用JsonConvert.SerializeObject方法,这是我的丢失数据的实体:

[DataContract]
public class MediaDTO : BaseEntityDTO
{
    [DataMember(IsRequired = true)]
    public int Id { get; set; }

    [DataMember(IsRequired = true)]
    public bool IsAlive { get; set; }

    [DataMember(IsRequired = true)]
    public string Description { get; set; }

    [DataMember(IsRequired = true)]
    public PidDTO Pid { get; set; }
}

[DataContract]
public class BaseEntityDTO
{ 
    [DataMember(IsRequired = true)]
    public bool IsDeleted { get; set; }

    [DataMember(IsRequired = true)]
    public DateTime AddedDate { get; set; }

    [DataMember(IsRequired = true)]
    public DateTime UpdatedDate { get; set; }
}

public class PidDTO : BaseEntityDTO
{
    public string PidId { get; set; }
    public VidDTO Vid { get; set; }
    public string Name { get; set; }
    public virtual bool IsFromUser { get; set; }
}

public VidDTO : BaseEntityDTO
{
    public virtual string VidId { get; set; }
    public virtual string Name { get; set; }
    public virtual bool IsFromUser { get; set; }
}

现在,当我查看json时,我看到了BaseEntityDTO类的所有属性,但看不到该类本身的其他属性.

知道为什么,实体或类似的东西有问题吗?

解决方法:

问题是您的PidDTO和VidDTO类型的属性没有被序列化.发生这种情况是因为其基本类型BaseEntityDTO标记为[DataContract],并且数据合同序列化是可选的.

解决方案也是用[DataContract]标记这些派生类型,然后用[DataMember]标记要序列化的所有成员:

[DataContract]
public class PidDTO : BaseEntityDTO
{
    [DataMember]
    public string PidId { get; set; }
    [DataMember]
    public VidDTO Vid { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public virtual bool IsFromUser { get; set; }
}

[DataContract]
public class VidDTO : BaseEntityDTO
{
    [DataMember]
    public virtual string VidId { get; set; }
    [DataMember]
    public virtual string Name { get; set; }
    [DataMember]
    public virtual bool IsFromUser { get; set; }
}

但是为什么这是必要的呢?从理论上讲,应用于基类的DataContractAttribute的存在不应影响您的派生类型,因为DataContractAttribute sets AttributeUsageAttribute.Inherited = false

[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Enum, Inherited = false, 
AllowMultiple = false)]
public sealed class DataContractAttribute : Attribute

但是,Json.NET不遵守DataContractAttribute的Inherited = false属性,而是将数据协定类型的所有派生类型解释为具有选择加入序列化,如here所述

[Json.NET] detects the DataContractAttribute on the base class and assumes opt-in serialization.

因此,您毕竟需要添加这些属性.

或者,如果仅使用数据协定属性来设置IsRequired = true,则可以改为使用[JsonProperty(Required = Required.AllowNull)]

public class MediaDTO : BaseEntityDTO
{
    [JsonProperty(Required = Required.AllowNull)]
    public int Id { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public bool IsAlive { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public string Description { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public PidDTO Pid { get; set; }
}

public class BaseEntityDTO
{
    [JsonProperty(Required = Required.AllowNull)]
    public bool IsDeleted { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public DateTime AddedDate { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public DateTime UpdatedDate { get; set; }
}

这使您的派生类型可以继续选择退出序列化.

标签:datacontract,serialization,json-net,json,c
来源: https://codeday.me/bug/20191118/2031575.html