NewtonSoft Json.Net对象的条件序列化

时间:2018-12-14 15:11:32

标签: serialization json.net

我对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”来验证其内部?

  • 是否可以编写用于验证对象本身而非成员的函数? 像这样:


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

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

2 个答案:

答案 0 :(得分:0)

您能为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();

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

答案 1 :(得分:0)

是的,您可以在ContractResolver中进行此操作。您拥有{{1}的instance,并且拥有(A类型的属性,因此您只需要在属性上询问B就可以了实例中的值。这就是您要寻找的ValueProvider。然后,您可以检查B以确定是否要序列化该属性。

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

B

如果class B { public string Name { get; set; } [JsonIgnore] public bool IsHidden { get; set; } } 为假,则可以在解析器中决定只想序列化B

IsHidden

这是一个有效的演示:https://dotnetfiddle.net/4MbQ0q

顺便说一句,我相当确定传递给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; } 的{​​{1}}永远不会为空,因为询问instance的属性是否应该是没有意义的如果没有ShouldSerialize,则将其序列化。将支票存入那里并没有什么坏处,但我认为您不需要它。