Newtonsoft JSON ShouldSerialize和继承

Cha*_*let 5 c# json.net asp.net-web-api

我有一个这样的课:

public class Foo
{
    public int Bar { get; set;}
}
Run Code Online (Sandbox Code Playgroud)

该类用于存储在NoSQL数据库中,因此我需要存储该Bar值.但是,我不想通过我的API公开这个值.所以我创建了一个继承Foo自我的API的类.

ShouldSerializeBar按照我在这里找到的文档创建了该方法.

public class Foo2 : Foo
{
    public bool ShouldSerializeBar()
    {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,不调用该方法.是否有针对此或其他方式实现此目的的解决方法?

dan*_*ana 7

public class Foo
{
    public int Bar { get; set;}

    public virtual bool ShouldSerializeBar()
    {
        return true;
    }
}

public class Foo2 : Foo
{
    public override bool ShouldSerializeBar()
    {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这就是我最终做的。它有效,但我想避免在我的基类中添加此方法。无论如何,它现在可以解决问题;) (2认同)

Jua*_*gui 6

You don't need to inherit from Foo if you use a IContractResolver.

From the docs

ShouldSerialize can also be set using an IContractResolver. Conditionally serializing a property using an IContractResolver is useful if you don't want to place a ShouldSerialize method on a class or you didn't declare the class and are unable to.

In your case something like this should work.

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (property.DeclaringType == typeof(Foo) && property.PropertyName == "Bar")
        {
            property.ShouldSerialize = instance => false;
        }

        return property;
    }
}
Run Code Online (Sandbox Code Playgroud)

And then you can use it like

var foo = new Foo();
foo.Bar = 1;

string json = JsonConvert.SerializeObject(foo,
        Formatting.Indented,
        new JsonSerializerSettings { ContractResolver = new ShouldSerializeContractResolver() });
Run Code Online (Sandbox Code Playgroud)

Though I don't know if this is more intrusive than the new class (Foo2) and the virtual method in its base, at least is another option ;)