使用 JsonConvert 进行序列化会丢失数据
Serialization with JsonConvert Loses Data
我在我的项目中使用 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
class 中的所有 属性,但没有看到 class本身。
知道为什么吗,是实体有问题还是类似问题?
问题 是您的 PidDTO
和 VidDTO
类型的属性没有被序列化。发生这种情况是因为它们的基本类型 BaseEntityDTO
标记为 [DataContract]
,并且数据契约序列化是 opt-in。
解决方法也是将这些派生类型标记为[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
applied to the base class should not affect your derived types, because 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
, you could switch to using [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; }
}
这允许您的派生类型继续选择退出序列化。
我在我的项目中使用 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
class 中的所有 属性,但没有看到 class本身。
知道为什么吗,是实体有问题还是类似问题?
问题 是您的 PidDTO
和 VidDTO
类型的属性没有被序列化。发生这种情况是因为它们的基本类型 BaseEntityDTO
标记为 [DataContract]
,并且数据契约序列化是 opt-in。
解决方法也是将这些派生类型标记为[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
applied to the base class should not affect your derived types, because 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
, you could switch to using [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; }
}
这允许您的派生类型继续选择退出序列化。