为什么 Json.net 不能正确序列化从 TreeNode 派生的 class?
Why doesn't Json.net properly serialize a class derived from TreeNode?
我有一个从 TreeNode
继承的 class,当我尝试序列化它时,它只是 returns 一个不是 JSON 字符串的字符串(如我所料)。
例如:
string json = JsonConvert.SerializeObject(new A());
输出:
"TreeNode: "
其中 A
定义为:
public class A : TreeNode { public int x { get; set; } }
如果我删除 TreeNode
继承,输出为:
{"x":0}
如果它继承自 TreeNode
,为什么它不序列化 属性?
注意:我过滤我的 class 以仅序列化我的 A
class 的 public 属性,使用合同:
public class ShouldSerializeContractResolver : DefaultContractResolver
{
private List<string> propertiesNames;
public ShouldSerializeContractResolver(Type type)
{
this.propertiesNames =
type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Select(p => p.Name)
.ToList();
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize =
instance =>
{
return propertiesNames.Contains(property.PropertyName);
};
return property;
}
}
然后使用以下方法序列化对象:
ShouldSerializeContractResolver contract = new ShouldSerializeContractResolver(typeof(CustomTreeNode));
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings() { ContractResolver = contract };
string json = JsonConvert.SerializeObject(groups, Formatting.Indented, jsonSerializerSettings);
但它 returns 与我在主题开头提到的相同的无效输出。
如果您谈论的是应用于它的 System.Windows.Forms.TreeNode
then the reason you are seeing this behavior is because TreeNode
has a [TypeConverter]
属性,这会导致 Json.Net 将其序列化为简单的字符串值而不是对象。
您可以通过几种不同的方式让它按照您想要的方式工作。
将 [JsonObject]
属性应用于您的自定义 TreeNode class
[JsonObject]
public class A : TreeNode
{
...
}
或者,在您的自定义 ContractResolver
中覆盖 CreateContract()
方法,以便它为您的自定义类型显式创建一个对象契约:
public class ShouldSerializeContractResolver : DefaultContractResolver
{
private Type myType;
private List<string> propertiesNames;
public ShouldSerializeContractResolver(Type type)
{
myType = type;
this.propertiesNames =
type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Select(p => p.Name)
.ToList();
}
protected override JsonContract CreateContract(Type objectType)
{
if (objectType == myType)
{
return CreateObjectContract(objectType);
}
return base.CreateContract(objectType);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize =
instance =>
{
return propertiesNames.Contains(property.PropertyName);
};
return property;
}
}
我有一个从 TreeNode
继承的 class,当我尝试序列化它时,它只是 returns 一个不是 JSON 字符串的字符串(如我所料)。
例如:
string json = JsonConvert.SerializeObject(new A());
输出:
"TreeNode: "
其中 A
定义为:
public class A : TreeNode { public int x { get; set; } }
如果我删除 TreeNode
继承,输出为:
{"x":0}
如果它继承自 TreeNode
,为什么它不序列化 属性?
注意:我过滤我的 class 以仅序列化我的 A
class 的 public 属性,使用合同:
public class ShouldSerializeContractResolver : DefaultContractResolver
{
private List<string> propertiesNames;
public ShouldSerializeContractResolver(Type type)
{
this.propertiesNames =
type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
.Select(p => p.Name)
.ToList();
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize =
instance =>
{
return propertiesNames.Contains(property.PropertyName);
};
return property;
}
}
然后使用以下方法序列化对象:
ShouldSerializeContractResolver contract = new ShouldSerializeContractResolver(typeof(CustomTreeNode));
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings() { ContractResolver = contract };
string json = JsonConvert.SerializeObject(groups, Formatting.Indented, jsonSerializerSettings);
但它 returns 与我在主题开头提到的相同的无效输出。
如果您谈论的是应用于它的 System.Windows.Forms.TreeNode
then the reason you are seeing this behavior is because TreeNode
has a [TypeConverter]
属性,这会导致 Json.Net 将其序列化为简单的字符串值而不是对象。
您可以通过几种不同的方式让它按照您想要的方式工作。
将
[JsonObject]
属性应用于您的自定义 TreeNode class[JsonObject] public class A : TreeNode { ... }
或者,在您的自定义
ContractResolver
中覆盖CreateContract()
方法,以便它为您的自定义类型显式创建一个对象契约:public class ShouldSerializeContractResolver : DefaultContractResolver { private Type myType; private List<string> propertiesNames; public ShouldSerializeContractResolver(Type type) { myType = type; this.propertiesNames = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) .Select(p => p.Name) .ToList(); } protected override JsonContract CreateContract(Type objectType) { if (objectType == myType) { return CreateObjectContract(objectType); } return base.CreateContract(objectType); } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); property.ShouldSerialize = instance => { return propertiesNames.Contains(property.PropertyName); }; return property; } }