【问题标题】:NewtonSoft Json.Net conditional serialization of objectNewtonSoft Json.Net 对象的条件序列化
【发布时间】:2018-12-14 15:11:31
【问题描述】:

我有一个关于 NewtonSoft Json.Net 序列化的问题。 我四处寻找,但未能找到解决方案。 SO中有一些问题与标题相似,但没有一个问题出现这种情况。

我需要的是防止某些对象在某些条件下被序列化。

示例: 给定这个类:

class A
{
    B b;
}

我们可以通过写来防止B被序列化:

class A
{
    B b;
    public bool ShouldSerializeb()
    {
        return false; //validate the condition you want.
    }
}

但如果我们有多个 B,我们最终不得不为每个 B 编写一个函数:

class A
{
    B b;
    B bb;
    B bbb;
    public bool ShouldSerializeb()
    {
        return false; //validate the condition you want.
    }

    public bool ShouldSerializebb()
    {
        return false; //validate the condition you want.
    }

    public bool ShouldSerializebbb()
    {
        return false; //validate the condition you want.
    } 
}

还有另一种方法:使用合约解析器

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    public new static readonly ShouldSerializeContractResolver Instance 
     = new ShouldSerializeContractResolver();
    protected override JsonProperty CreateProperty(MemberInfo member, 
    MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyType == typeof(B))
        {
            property.ShouldSerialize =
                instance =>
                {
                    if (instance == null)
                        return false;

                    // The problem is that "instance" here is A and not B
                    // preventing the necessary validation

                    return false; //validate the condition you want.
                };
        }
        return property;
    }
}

问题:

  • 有没有办法让“实例为“B”以验证其内部结构?

  • 有没有办法编写函数来验证对象本身而不是成员? 像这样:

B类 { 公共布尔应该序列化() { 返回假; //验证你想要的条件。 } }

谢谢 (我可能应该在 github 上发布这个,但我们习惯于将问题集中在 SO)

【问题讨论】:

    标签: serialization json.net


    【解决方案1】:

    是的,您可以在ContractResolver 中执行此操作。你有instanceA)和属性(B 类型),所以你只需要询问属性上的ValueProvider 来给你实例的值。那就是您要寻找的B。然后您可以检查B 以决定是否序列化该属性。

    例如,如果B 类看起来像这样:

    class B
    {
        public string Name { get; set; }
        [JsonIgnore]
        public bool IsHidden { get; set; }
    }
    

    您可以在解析器中决定,如果IsHidden 为假,您只想序列化B

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyType == typeof(B))
        {
            property.ShouldSerialize = instance =>
            {
                if (instance == null) return false;
    
                B b = (B)property.ValueProvider.GetValue(instance);
    
                // validate the condition you want, for example:
                return b != null && !b.IsHidden;
            };
        }
        return property;
    }
    

    这是一个工作演示:https://dotnetfiddle.net/4MbQ0q

    顺便说一句,我相当肯定传递给ShouldSerializeinstance 永远不会为空,因为如果没有,询问是否应该序列化A 的属性是没有意义的A 首先。在那里办理登机手续并没有什么坏处,但我认为你不需要它。

    【讨论】:

    • 谢谢。回复晚了非常抱歉。我会在新的一年工作时检查一下。新年快乐。
    【解决方案2】:

    你能为 ShouldSerialize 写两个方法吗?

    public bool ShouldSerialize(typeof(B))
    {
        return false;
    }
    

    或在 B 类中编写一个覆盖并将其称为 B 类:A 然后

    Class B : A {
        public overide bool ShouldSerialize()
        {
            return false;
        }
    }
    
    Class A {
        public bool ShouldSerialize(){
            return true;
        }
    }
    

    然后调用 b.ShouldSerialize();或 bb.ShouldSerialize();

    值得一试,可能误解了这个问题,但嘿哦,其他人会及时知道的。

    【讨论】:

    • 我不调用ShouldSerialize方法,Json.net这样做是为了知道它是否应该序列化成员。它有点像回调。问题是,如果我在 A 类中有 10 个 B,我需要创建 10 个函数来验证它们中的每一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2017-05-26
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多