Это моя первая попытка сериализовать / десериализовать дерево. Работает отлично, за исключением Path
. Он должен быть создан из root, но десериализация начинается с листьев.
var root = new Node(null, "rootName");
var tree = new Tree(root);
root.AddChild("childName");
var str = JsonConvert.SerializeObject(tree, Newtonsoft.Json.Formatting.Indented);
var treeRestored = JsonConvert.DeserializeObject<Tree>(str);
...
class Node
{
public IReadOnlyList<Node> Children => _children;
[JsonIgnore]
public string Path { get; } // needs parent
[JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
public Node Parent { get; private set; }
public string Name { get; }
public Node(Node parent, string name)
{
Name = name;
Parent = parent;
Path = (parent == null ? "" : (parent.Name + ".")) + name;
_children = new List<Node>();
}
[JsonConstructor]
private Node(string Name, List<Node> Children)
{
this.Name = Name;
_children = Children;
foreach (var child in _children)
{
child.Parent = this;
}
}
public void AddChild(string name)
{
_children.Add(new Node(this, name));
}
private readonly List<Node> _children;
}
class Tree
{
public Node Root;
public Tree(Node root)
{
Root = root;
}
}
Итак, я попробовал следующее. Я удалил JsonProperty
из свойства Parent
, изменил команду сериализации и изменил JSON конструктор.
var str = JsonConvert.SerializeObject(tree, Newtonsoft.Json.Formatting.Indented,
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
[JsonConstructor]
private Node(string name, Node parent)
{
Name = name;
Parent = parent;
if (Parent != null) // Rebuild path
{
parent._children.Add(this);
Path = parent.Name + "." + Name;
}
else
{
Path = Name;
}
_children = new List<Node>();
}
С этими изменениями строка сериализации выглядит так:
{
"$id": "1",
"Root": {
"$id": "2",
"Children": [
{
"$id": "3",
"Children": [],
"Parent": {
"$ref": "2"
},
"Name": "childName"
}
],
"Parent": null,
"Name": "rootName"
}
}
Эта строка Json содержит достаточно информации, чтобы сначала создать root, а затем дочерний элемент. Но JsonConverter все равно начинается с листьев. Как я могу изменить порядок?
Я знаю, что могу использовать OnDeserialized
, но это последнее средство для меня.