更新时间:2023-02-18 16:11:50
您的问题不包括您的Node<T>
类的声明.在其他(大型)类中,我认为它一定是这样的:
Your question does not include the declaration of your Node<T>
class. From the rest of the (large) class, I reckon it must be something like:
public class Node<T> : IEqualityComparer, IEnumerable<T>
这说明了您的问题:
T
实现IEnumerable<T>
.IEnumerable
序列化为JSON数组 Value
属性未序列化.IEnumerable<T>
for some T
.IEnumerable
as a JSON array.Value
property is not serialized.如果您希望继续使Node<T>
工具实现IEnumerable
,则需要创建一个自定义 JsonConverter
:
If you wish to continue making your Node<T>
implement IEnumerable
, you need to create a custom JsonConverter
for it:
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
public class NodeConverter : JsonConverter
{
class NodeWrapper<T>
{
public T value { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public IEnumerable<Node<T>> children { get; set; }
}
static Type GetNodeValueType(Type type)
{
return type.BaseTypesAndSelf().Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Node<>)).Select(t => t.GetGenericArguments()[0]).FirstOrDefault();
}
public override bool CanConvert(Type objectType)
{
return GetNodeValueType(objectType) != null;
}
object ReadJsonGeneric<T>(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var wrapper = serializer.Deserialize<NodeWrapper<T>>(reader);
if (wrapper == null)
return existingValue;
var node = existingValue as Node<T> ?? new Node<T>(wrapper.value);
node.Value = wrapper.value;
if (wrapper.children != null)
foreach (var child in wrapper.children)
node.Add(child);
return node;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var method = GetType().GetMethod("ReadJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
var genericMethod = method.MakeGenericMethod(new[] { GetNodeValueType(objectType) });
return genericMethod.Invoke(this, new object[] { reader, objectType, existingValue, serializer });
}
void WriteJsonGeneric<T>(JsonWriter writer, object value, JsonSerializer serializer)
{
var node = (Node<T>)value;
serializer.Serialize(writer, new NodeWrapper<T> { value = node.Value, children = (node.Children.Any() ? node.Children : null)});
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var method = GetType().GetMethod("WriteJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
var genericMethod = method.MakeGenericMethod(new[] { GetNodeValueType(value.GetType()) });
genericMethod.Invoke(this, new object[] { writer, value, serializer });
}
}
通过调用您的Add(Node<T> child)
方法,转换器还可以确保设置了父级后向引用.
By calling your Add(Node<T> child)
method, the converter also makes sure the parent back-references are set.
然后像这样使用它:
[JsonConverter(typeof(NodeConverter))]
public class Node<T> : IEqualityComparer, IEnumerable<T>
{