我只想要对象的第一个深度级别(我不需要任何子级)。我愿意使用任何可用的图书馆。大多数库仅在达到递归深度时才会抛出异常,而不仅仅是忽略。如果这不可能,是否有一种方法可以忽略给定特定数据类型的特定成员的序列化?
编辑:假设我有一个像这样的对象:
class MyObject { String name = "Dan"; int age = 88; List<Children> myChildren = ...(lots of children with lots of grandchildren); }
我想删除任何子级(甚至是复杂类型)以返回这样的对象:
class MyObject { String name = "Dan"; int age = 88; List<Children> myChildren = null; }
在Json.NET中,可以使用JsonWriter和序列化程序之间的一些协调ContractResolver。
JsonWriter
ContractResolver
自定义JsonWriter在对象启动时增加计数器,然后在结束时再次减少计数器。
public class CustomJsonTextWriter : JsonTextWriter { public CustomJsonTextWriter(TextWriter textWriter) : base(textWriter) {} public int CurrentDepth { get; private set; } public override void WriteStartObject() { CurrentDepth++; base.WriteStartObject(); } public override void WriteEndObject() { CurrentDepth--; base.WriteEndObject(); } }
定制对将用于验证当前深度的所有属性ContractResolver应用特殊ShouldSerialize谓词。
ShouldSerialize
public class CustomContractResolver : DefaultContractResolver { private readonly Func<bool> _includeProperty; public CustomContractResolver(Func<bool> includeProperty) { _includeProperty = includeProperty; } protected override JsonProperty CreateProperty( MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); var shouldSerialize = property.ShouldSerialize; property.ShouldSerialize = obj => _includeProperty() && (shouldSerialize == null || shouldSerialize(obj)); return property; } }
下面的方法显示了这两个自定义类如何一起工作。
public static string SerializeObject(object obj, int maxDepth) { using (var strWriter = new StringWriter()) { using (var jsonWriter = new CustomJsonTextWriter(strWriter)) { Func<bool> include = () => jsonWriter.CurrentDepth <= maxDepth; var resolver = new CustomContractResolver(include); var serializer = new JsonSerializer {ContractResolver = resolver}; serializer.Serialize(jsonWriter, obj); } return strWriter.ToString(); } }
以下测试代码演示了将最大深度分别限制为1级和2级。
var obj = new Node { Name = "one", Child = new Node { Name = "two", Child = new Node { Name = "three" } } }; var txt1 = SerializeObject(obj, 1); var txt2 = SerializeObject(obj, 2); public class Node { public string Name { get; set; } public Node Child { get; set; } }