I am deserialising the document below which contains references using two different classes which hold the same data. One is being deserialised with constructor injection and the other with property injection. The constructor injection class fails to set the parent reference but the property injection class is fine. Surely they should both have the same data injected correctly regardless of the way it is done. I have written a test to demonstrate.
Am I missing something?
{
"Id": "1472538848721372202",
"Key": "website",
"Root": {
"$id": "1",
"Id": "1472459628771017730",
"Type": "cras",
"Content": {
"Name": "lorem"
},
"Parent": null,
"Children": [{
"$id": "2",
"Id": "1472459628812960771",
"Type": "morbi",
"Content": {
"Name": "ipsumdolor"
},
"Parent": {
"$ref": "1"
}
}]
}
}
Deserialisation test.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using Xunit;
using static dataapi.tests.HierarchyCtor;
using static dataapi.tests.HierarchyProp;
namespace dataapi.tests
{
public class JsonConstructorPropTest
{
[Fact]
public void GivenTheASameJsonWithParentReferencesWhenParsedUsingConstuctorAndPropertyInjectionThenTheTwoObjectShouldHoldTheSameData()
{
const string RootId = "1472459628771017730";
var json = "{\"Id\":\"1472538848721372202\",\"Key\":\"website\",\"Root\":{\"$id\":\"1\",\"Id\":\"1472459628771017730\",\"Type\":\"cras\",\"Content\":{\"Name\":\"lorem\"},\"Parent\":null,\"Children\":[{\"$id\":\"2\",\"Id\":\"1472459628812960771\",\"Type\":\"morbi\",\"Content\":{\"Name\":\"ipsumdolor\"},\"Parent\":{\"$ref\":\"1\"}}]}}";
var hierarchyProp = JsonConvert.DeserializeObject<HierarchyProp>(json);
TraverseHierarchyProp(hierarchyProp.Root, node =>
{
if (node.Id == RootId)
{
Assert.Null(node.Parent);
}
else
{
Assert.NotNull(node.Parent);
}
});
var hierarchyCtor = JsonConvert.DeserializeObject<HierarchyCtor>(json);
TraverseHierarchyCtor(hierarchyCtor.Root, node =>
{
if (node.Id == RootId)
{
Assert.Null(node.Parent);
}
else
{
Assert.NotNull(node.Parent);
}
});
}
private void TraverseHierarchyCtor(NodeCtor node, Action<NodeCtor> callback)
{
for (int index = 0; index < node.Children.Length; index++)
{
TraverseHierarchyCtor(node.Children[index], callback);
}
callback(node);
}
private void TraverseHierarchyProp(NodeProp node, Action<NodeProp> callback)
{
for (int index = 0; index < node.Children.Length; index++)
{
TraverseHierarchyProp(node.Children[index], callback);
}
callback(node);
}
}
[JsonObject(IsReference = false)]
public class HierarchyCtor
{
private readonly DateTime _updatedAt;
private readonly DateTime _createdAt;
private readonly NodeCtor _root;
private readonly string _key;
private readonly string _id;
public HierarchyCtor(string id, string key, NodeCtor root, DateTime createdAt, DateTime updatedAt)
{
_id = id;
_key = key;
_root = root;
_createdAt = createdAt;
_updatedAt = updatedAt;
}
public NodeCtor Root
{
get { return _root; }
}
[JsonObject(IsReference = true)]
public class NodeCtor
{
private readonly string _id;
private readonly string _type;
private readonly JObject _content;
private readonly NodeCtor[] _children;
private readonly NodeCtor _parent;
private readonly DateTime _updatedAt;
private readonly DateTime _createdAt;
public NodeCtor(string id, string type, JObject content, DateTime createdAt, DateTime updatedAt, NodeCtor Parent, params NodeCtor[] children)
{
_id = id;
_type = type;
_content = content;
_createdAt = createdAt;
_updatedAt = updatedAt;
_parent = Parent;
_children = children ?? new NodeCtor[] { };
}
public string Id
{
get { return _id; }
}
public NodeCtor Parent
{
get { return Parent; }
}
public NodeCtor[] Children
{
get { return _children; }
}
}
}
[JsonObject(IsReference = false)]
public class HierarchyProp
{
[JsonObject(IsReference = true)]
public class NodeProp
{
public NodeProp()
{
Children = new NodeProp[] { };
}
public string Id { get; set; }
public string Type { get; set; }
public JObject Content { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public NodeProp Parent { get; set; }
public NodeProp[] Children { get; set; }
}
public string Id { get; set; }
public string Key { get; set; }
public NodeProp Root { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
}