How to serialize or deserialize a JSON Object to a certain depth in C#?

后端 未结 4 1052
鱼传尺愫
鱼传尺愫 2020-12-05 14:03

I only want the first depth level of an object (I do not want any children). I am willing to use any library available. Most libraries will merely throw an exception when

4条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-05 14:37

    This is possible in Json.NET using some coordination between the JsonWriter and the serializer's ContractResolver.

    A custom JsonWriter increments a counter when an object is started and then decrements it again when it ends.

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

    A custom ContractResolver applies a special ShouldSerialize predicate on all properties that will be used to verify the current depth.

    public class CustomContractResolver : DefaultContractResolver
    {
        private readonly Func _includeProperty;
    
        public CustomContractResolver(Func 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;
        }
    }
    

    The following method shows how these two custom classes work together.

    public static string SerializeObject(object obj, int maxDepth)
    {
        using (var strWriter = new StringWriter())
        {
            using (var jsonWriter = new CustomJsonTextWriter(strWriter))
            {
                Func include = () => jsonWriter.CurrentDepth <= maxDepth;
                var resolver = new CustomContractResolver(include);
                var serializer = new JsonSerializer {ContractResolver = resolver};
                serializer.Serialize(jsonWriter, obj);
            }
            return strWriter.ToString();
        }
    }
    

    The following test code demonstrates limiting the maximum depth to 1 and 2 levels respectively.

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

提交回复
热议问题