一尘不染

如何在C#中将JSON对象序列化或反序列化到一定深度?

json

我只想要对象的第一个深度级别(我不需要任何子级)。我愿意使用任何可用的图书馆。大多数库仅在达到递归深度时才会抛出异常,而不仅仅是忽略。如果这不可能,是否有一种方法可以忽略给定特定数据类型的特定成员的序列化?

编辑:假设我有一个像这样的对象:

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;
}

阅读 326

收藏
2020-07-27

共1个答案

一尘不染

Json.NET中,可以使用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谓词。

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; }
}
2020-07-27