我有一个表示组织结构图中员工的通用树结构。
该树由自定义Node<Person>
对象的图组成,这些对象具有相互引用和其他属性,如Level,显示它们在树中的级别、父对象、可能性等。
我必须将这个组织结构图的一部分从一个特定的人向下序列化到他们下面的每个人,并且我在Node对象上有一个名为SelfAndDescendants()
的方法,它返回一个IEnumerable<Node<Person>>
。
所以基本上,我在树中定位特定人的Node
,然后在IEnumerable
中获取他们和他们的所有后代。这部分工作正常。
这就是我陷入困境的地方。现在我需要将Nodes
的IEnumerable
集合转换为层次JSON。
我的第一次尝试只是直接把它扔给JSON序列化程序,但这不起作用(我也没有真正期望它起作用),因为它是一组通用的Node
对象。Node
对象上有一个Value
属性,它将返回一个Person
对象。。。这就是我需要进入JSON(只是名称)的地方。
string json = JsonConvert.SerializeObject(personNode.SelfAndDescendants.ToList());
这显然是在尝试序列化List<Node<Person>>
,这不是我所需要的。JSON返回所需要的只是一个具有简单Person
对象的Name
的分层格式。没有别的。
我必须在循环中手动执行任何操作才能构建自定义JSON并返回吗?
这不是这篇文章的重复,因为我在这里处理的是一个通用递归树,而不是一个简单的通用数据结构。
我必须实现自定义JsonConverter
吗?这是如何处理树中的一系列Node
对象的?
Node类有各种各样的属性,但它基本上看起来是这样的:
public class Node<T> : IEqualityComparer, IEnumerable<T>, IEnumerable<Node<T>> {
public Node(T value) {
Value = value;
}
public Node<T> this[int index] {
get {
return _children[index];
}
}
public Node<T> Add(T value, int index = -1) {
var childNode = new Node<T>(value);
Add(childNode, index);
return childNode;
}
public IEnumerable<Node<T>> SelfAndDescendants {
get {
return this.ToIEnumarable().Concat(Children.SelectMany(c => c.SelfAndDescendants));
}
}
}
Person类只是代表一个人的POCO类。这个类已经为系统的另一部分正确地序列化为JSON。
[JsonObject]
public class Person {
public string Title { get; set; }
public DateTime DateOfBirth { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public Gender Gender { get; set; }
public List<StreetAddress> Addresses { get; set; }
... etc
}
所需的输出是一个组织图,用JSON显示人员的级别。所以员工在老板手下,那个老板在老板手下等等。
JSON在这方面非常简单,它只是人名和头衔。它甚至可以只是每个员工的一个字符串。
是的,考虑到您的限制,我认为创建自定义JsonConverter
是解决这种情况的合适方案。实际上,只要Node<T>
具有公共属性,至少允许对Value
和Children
进行读取访问,编写起来就非常简单。您不必担心循环;当串行器通过CCD_ 22调用在CCD_。
以下是我的写作方式:
public class OrgChartConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Node<Person>));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Node<Person> node = (Node<Person>)value;
JObject obj = new JObject();
obj.Add("Name", node.Value.Name);
obj.Add("Subordinates", JArray.FromObject(node.Children, serializer));
obj.WriteTo(writer);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后,使用这样的转换器:
var settings = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new OrgChartConverter() },
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(rootNode, settings);
下面是一个演示:https://dotnetfiddle.net/BfdFdW
您想描述如何通过在类和所需成员上添加序列化属性来序列化这个类,然后将其序列化为字符串
string nodes = JsonConvert.SerializeObject<Node<Person>>(personNode);
[JsonObject]
public class Node<T> : IEqualityComparer, IEnumerable<T>, IEnumerable<Node<T>> {
[JsonProperty]
public IEnumerable<Node<T>> Children { get { return _children; } }
...
}
JSON.NET序列化属性