Reputation: 4245
I'm using JsonConvert
in my project in order to make a json
string from my object, but something weird is happening, one of entities losses data in the process, which is weird because when I'm debugging, the entity has values, but for some reason it gets lost during the process.
I use the JsonConvert.SerializeObject method, and this is my entity which looses data:
[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; }
}
Now, when I Look at the json
, and I see all of the property from the BaseEntityDTO
class, but not the other properties of the class itself.
Any idea why, is there a problem with the entities or something like that?
Upvotes: 5
Views: 2496
Reputation: 116585
The problem is that the properties of your PidDTO
and VidDTO
types are not being serialized. This is happening because their base type BaseEntityDTO
is marked with [DataContract]
, and data contract serialization is opt-in.
The solution is also to mark these derived types with [DataContract]
, then mark all members you wish to serialize with [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; }
}
But why should this be necessary? In theory, the presence of the 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
However, Json.NET does not respect the Inherited = false
attribute of DataContractAttribute
and interprets all derived types of a data contract type as having opt-in serialization, as is explained here
[Json.NET] detects the DataContractAttribute on the base class and assumes opt-in serialization.
So you need to add those attributes after all.
Alternatively, if you are only using data contract attributes to set IsRequired = true
, you could switch to using [JsonProperty(Required = Required.AllowNull)]
instead:
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; }
}
This allows your derived types to continue to have opt-out serialization.
Upvotes: 3