如何使用Newtonsoft JSON阻止DependencyObjects上的DependencyObjectType信息的序列化?

时间:2016-02-10 22:02:46

标签: c# json wpf serialization

使用 Newoftoft的JSON (版本8.0.0)为 .Net / C#序列化DependencyObject派生类时,我注意到它始终序列化{{1 }}和DependencyObjectType个对象以及我的所有衍生类属性。由于DispatcherDependencyObjectType对象来自我继承的Dispatcher类,如何添加智能标记或属性(例如DependencyObject)以防止它们被序列化?或者我或许是以错误的方式思考它?

示例类代码:

[JsonIgnore]

串行器代码:

public class MyClass : DependencyObject
{
    public int MyProperty
    {
        get { return (int)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));
}

当序列化时,我得到了这个巨大的blob(除了顶线以外都是不需要的):

JsonSerializer serializer = new JsonSerializer();
using (StreamWriter sw = new StreamWriter(filePath))
using (JsonWriter jw = new JsonTextWriter(sw))
{
    serializer.Serialize(jw, MyInstance);
}

2 个答案:

答案 0 :(得分:3)

您可以使用 OptIn 方法来禁止类型层次结构中除必需属性之外的所有属性的序列化:

[JsonObject(MemberSerialization = MemberSerialization.OptIn)]

使用以下命令标记序列化的属性:

[JsonProperty]

答案 1 :(得分:1)

您可以使用MemberSerialization.OptIn[JsonProperty]标记您的类型,如@Filip's answer中所述。

第二个答案是使用省略指定基类的所有属性或基类集合的custom ContractResolver

/// <summary>
/// Contract resolver to ignore properties of a single given type.
/// </summary>
/// <typeparam name="T"></typeparam>
public class IgnoreTypePropertiesContractResolver<T> : IgnoreTypePropertiesContractResolver
{
    // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
    // http://www.newtonsoft.com/json/help/html/ContractResolver.htm
    // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
    // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
    static IgnoreTypePropertiesContractResolver<T> instance;

    static IgnoreTypePropertiesContractResolver() { instance = new IgnoreTypePropertiesContractResolver<T>(); }

    public static IgnoreTypePropertiesContractResolver<T> Instance { get { return instance; } }

    IgnoreTypePropertiesContractResolver() : base(new[] { typeof(T) }) { }
}

/// <summary>
/// Contract resolver to ignore properties of any number of given types.
/// </summary>
public class IgnoreTypePropertiesContractResolver : DefaultContractResolver
{
    readonly HashSet<Type> toIgnore;
    readonly HashSet<Type> toIgnoreAndBase;

    public IgnoreTypePropertiesContractResolver(IEnumerable<Type> toIgnore)
    {
        if (toIgnore == null)
            throw new ArgumentNullException();
        this.toIgnore = new HashSet<Type>(toIgnore);
        this.toIgnoreAndBase = new HashSet<Type>(toIgnore.SelectMany(t => t.BaseTypesAndSelf()));
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var list = base.CreateProperties(type, memberSerialization);
        if (type.BaseTypesAndSelf().Any(t => toIgnore.Contains(t)))
        {
            var filtered = list.Where(p => !toIgnoreAndBase.Contains(p.DeclaringType)).ToList();
            return filtered;
        }
        return list;
    }
}

public static class TypeExtensions
{
    public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
    {
        while (type != null)
        {
            yield return type;
            type = type.BaseType;
        }
    }
}

使用自定义合约解析程序,无需为每种类型添加属性。

然后序列化如下:

var settings =  new JsonSerializerSettings { ContractResolver = IgnoreTypePropertiesContractResolver<DependencyObject>.Instance };
var json = JsonConvert.SerializeObject(new MyClass { MyProperty = 101 }, settings);