如何在 C# 中将 JSON 对象序列化或反序列化到一定深度? [英] How to serialize or deserialize a JSON Object to a certain depth in C#?
问题描述
我只想要对象的第一个深度级别(我不想要任何孩子).我愿意使用任何可用的库.大多数库只会在达到递归深度时抛出异常,而不是忽略.如果这是不可能的,有没有办法忽略给定特定数据类型的某些成员的序列化?
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 the recursion depth is reached, instead of just ignoring. If this isn't possible, is there a way to ignore serialization of certain members given a certain datatype?
假设我有一个这样的对象:
Let's say I have an object like so:
class MyObject
{
String name = "Dan";
int age = 88;
List<Children> myChildren = ...(lots of children with lots of grandchildren);
}
我想删除任何子项(甚至是复杂类型)以返回这样的对象:
I want to remove any children (complex types even) to return an object like this:
class MyObject
{
String name = "Dan";
int age = 88;
List<Children> myChildren = null;
}
推荐答案
这可以在 Json.NET 中使用JsonWriter
和序列化程序的 ContractResolver
.
This is possible in Json.NET using some coordination between the JsonWriter
and the serializer's ContractResolver
.
自定义 JsonWriter
在对象启动时递增计数器,然后在对象结束时再次递减.
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();
}
}
自定义ContractResolver
应用特殊的ShouldSerialize
将用于验证当前深度的所有属性的谓词.
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<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;
}
}
以下方法展示了这两个自定义类如何协同工作.
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<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 级.
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; }
}
这篇关于如何在 C# 中将 JSON 对象序列化或反序列化到一定深度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!