为什么Json.net没有正确序列化从TreeNode派生的类?

时间:2015-03-16 20:43:06

标签: c# json serialization json.net

我有一个继承自TreeNode的类,当我尝试序列化时,它只返回一个不是JSON字符串的字符串(正如我所料)。

例如:

string json = JsonConvert.SerializeObject(new A());

输出:

"TreeNode: "

A定义为:

public class A : TreeNode { public int x { get; set; } }

如果删除TreeNode继承,则输出为:

{"x":0}

如果它继承自TreeNode,为什么它不会序列化属性? 注意:我使用合同过滤我的类以仅序列化A类的公共属性:

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

但它返回与我在主题开头提到的相同的无效输出。

1 个答案:

答案 0 :(得分:2)

如果您正在谈论System.Windows.Forms.TreeNode,那么您看到此行为的原因是因为TreeNode已应用[TypeConverter]属性,这会导致Json.Net序列化它是一个简单的字符串值而不是一个对象。

你可以通过几种不同的方式让它以你想要的方式工作。

  1. [JsonObject]属性应用于自定义TreeNode类

    [JsonObject]
    public class A : TreeNode
    { 
        ...
    }
    
  2. 或者,覆盖自定义CreateContract()中的ContractResolver方法,以便明确为您的自定义类型创建对象合约:

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