I am trying to deserialize following JSON (simplified) to pointout the issue. The SampleRuleSet loses the Parent using $ref information whereas it exist in the JSON, and interesting for all the Children underneath SampleRuleSet have the Parent information available after deserialization.
It's a very strange behavior i have encountered and my researching didn't lead me to any concrete solution. I do however think its happening due to the ordering of the elements for which i used OrderedContractResolver
class from the following post but issue is still there.
{
"$id": "119",
"$type": "FSX.Client.Entities.RuleFolder, FSX.Client.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Children": [
{
"$id": "120",
"$type": "FSX.Client.Entities.RuleSet, FSX.Client.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Children": [
{
"$id": "121",
"$type": "FSX.Client.Entities.SetValue, FSX.Client.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Id": "d835028e-f630-42fa-b77d-af1b8abbc7a3",
"Name": "iterator",
"Parent": {
"$ref": "120"
}
},
{
"$id": "138",
"$type": "FSX.Client.Entities.SetValue, FSX.Client.Entities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"Id": "0101075c-c9dc-4f9d-9681-c72cc278e69f",
"Name": "Set_pvFv",
"Parent": {
"$ref": "120"
}
}
],
"Id": "b87ee6b6-a461-4669-bfce-31d5ed821458",
"Name": "SampleRuleSet",
"Parent": {
"$ref": "119"
}
}
],
"Id": "5d950d31-1eec-4beb-ab11-21c20b183f81",
"Name": "Financial",
"Parent": null
}
Following is my Services API settings:
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new OrderedContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
options.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
options.SerializerSettings.TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Full;
}
);
And i have similar settings at the consuming end.
Classes:
[DataContract]
public abstract class GenericRule : ClientEntity
{
protected GenericRule() : this(null) { }
protected GenericRule(string name)
{
Name = name;
}
[DataMember]
public string Name { get; set; }
[DataMember]
public ContainerRule Parent { get; set; }
}
[DataContract]
public abstract class ContainerRule : GenericRule
{
[DataMember(Name = nameof(Children))]
protected ObservableCollection<GenericRule> _children =
new ObservableCollection<GenericRule>();
public IEnumerable<GenericRule> Children => _children.AsEnumerable();
}
[DataContract]
public abstract class ActionRule : GenericRule { }
[DataContract]
public class Entity : ClientEntity { }
[DataContract]
public class RuleFolder : ContainerRule
{
private RuleFolder() { }
public RuleFolder(Entity entity) { } // the only way to construct this object is by using this ctor
}
[DataContract]
public class RuleSet : ContainerRule { }
[DataContract]
public class SetValue : ActionRule { }
One important bit, i have not decorated any of my class properties with [JsonProperty]
, they are just decorated with [DataMember]
, and my intend is also not to decorate so i am looking for solution without attribute decoration.