使用json.net

时间:2016-02-19 09:47:35

标签: c# json.net

我有一个类定义如下的场景:

class MyObject
{
    public DataDictionary MyObjectData { get; set; }

    public bool ShouldSerializeMyObjectData() { return true; }
    public bool ShouldDeserializeMyObjectData() { return false; }
}

当我尝试使用JSON.net序列化/反序列化该类时,会考虑ShouldSerialize,而不是ShouldDeserialize

根据文档,两者都应该像我猜的那样工作。有什么特别值得我知道的吗?更一般地说,我应该如何处理我想序列化属性但不反序列化它的场景?

如果重要的话,我会使用Json.NET 8.0

感谢您的帮助。

1 个答案:

答案 0 :(得分:8)

对您的问题的简短回答是,自动检查ShouldDeserialize{PropertyName}()目前尚未实施ShouldSerialize{PropertyName}()更长的答案和解决方法。

Json.NET在内部使用类JsonProperty来定义如何将JSON属性映射到.NET成员或构造函数参数的协定。它有两个谓词属性ShouldSerializeShouldDeserialize,当非null时,分别阻止属性被序列化和反序列化。初始化每个JsonPropertyContractResolver的工作。对于每个属性{PropertyName},Json.NET的default contract resolver会自动检查是否存在public bool ShouldSerialize{PropertyName}()方法。如果存在这样的方法,它会在ShouldSerialize谓词中添加对它的调用,从而在方法返回false时抑制序列化。这是因为通过方法ShouldSerialize{PropertyName}()控制属性序列化是由例如XmlSerializer支持的标准模式。有关更多背景信息,请参阅相关的Json.NET release notes

例如,在以下课程中,MyObjectData的序列化将被取消,除非MyObjectData.Count > 0

class MyObject
{
    public DataDictionary MyObjectData { get; set; }

    public bool ShouldSerializeMyObjectData() { return MyObjectData != null && MyObjectData.Count > 0; }
}

JsonProperty.ShouldDeserialize但是,默认合约解析程序永远不会设置它。这可能是因为没有标准的反序列化模式等同于ShouldSerialize{PropertyName}(),因此Newtonsoft从未有过实现这种模式的请求。然而,正如您所注意到的,存在支持这种模式的基础架构,因此应用程序可以创建custom contract resolvers来实现这一目标。实际上,Json.NET在自己的test suite中有一个这样的合同解析器的例子:

public class ShouldDeserializeContractResolver : DefaultContractResolver
{
    public static new readonly ShouldDeserializeContractResolver Instance = new ShouldDeserializeContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        MethodInfo shouldDeserializeMethodInfo = member.DeclaringType.GetMethod("ShouldDeserialize" + member.Name);

        if (shouldDeserializeMethodInfo != null)
        {
            property.ShouldDeserialize = o => { return (bool)shouldDeserializeMethodInfo.Invoke(o, null); };
        }

        return property;
    }
}

public class ShouldDeserializeTestClass
{
    [JsonExtensionData]
    public IDictionary<string, JToken> ExtensionData { get; set; }

    public bool HasName { get; set; }
    public string Name { get; set; }

    public bool ShouldDeserializeName()
    {
        return HasName;
    }
}

如果要有条件地抑制属性的反序列化,即使存在于JSON中,也可以考虑使用(和caching)此合约解析程序。