我怎样才能“un-JsonIgnore”派生类中的属性?

时间:2015-02-23 12:46:47

标签: c# .net json json.net jsonserializer

我正在使用Newtonsoft's JsonSerializer来序列化某些类。

由于我想在序列化过程中省略我班级的一个字段,我将其声明如下:

[JsonIgnore]
public int ParentId { get; set; }

这很有用,但我现在面临一个新问题:在派生类中,我希望这个字段出现(并且在这个特定的派生类中只执行 )。

我一直在查看文档和互联网上的一种方法来覆盖子类中的这个设置(我想我需要像[JsonStopIgnore]这样的东西,但我找不到任何接近的东西。)< / p>


  • 我有什么方法可以强制JsonSerializer重新获取此属性吗?
  • 是否可以将属性明确标记为[JsonIgnore],但基类中仅

5 个答案:

答案 0 :(得分:13)

“覆盖”[JsonIgnore]属性行为的唯一方法是使用契约解析器,正如@Yuval Itzchakov在他的回答中很好地解释的那样。

但是,还有另一种可能对您有用的解决方案:您可以在类中实现[JsonIgnore]方法来控制ShouldSerializeParentId()属性,而不是使用ParentId属性。被序列化。在基类中,使此方法返回false;然后,覆盖派生类中的方法以返回true。 (此功能在Json.Net中称为conditional property serialization。)

public class Base
{
    public int Id { get; set; }
    public int ParentId { get; set; }

    public virtual bool ShouldSerializeParentId()
    {
        return false;
    }
}

public class Derived : Base 
{ 
    public override bool ShouldSerializeParentId()
    {
        return true;
    }
}

小提琴:https://dotnetfiddle.net/65sCSz

答案 1 :(得分:9)

您可以通过创建自定义DefaultContractResolver并覆盖其CreateProperty方法来执行此操作。

例如,给定Foo基础和派生Bar

public class Foo
{
    [JsonIgnore]
    public string Name { get; set; }
    public int Age { get; set; }
}

public class Bar : Foo 
{ }

您可以创建以下合约解析程序:

public class MyTypeContractResolver<T> : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member,
                                                   MemberSerialization
                                                       memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        property.Ignored = false;
        property.ShouldSerialize = propInstance => property.DeclaringType != typeof (T);
        return property;
    }
}

这会将所有属性设置为Ignored = false,然后按给定的谓词分析它们:

propInstance => property.DeclaringType != typeof (T);

在我们的案例中,“只有当它们不属于Foo类型时才应序列化”(因为Foo是DeclaryingType)。

然后,当您要反序列化时,将合同解析程序的实例传递给JsonSerializerSettings

var bar = new Bar();
var result = JsonConvert.SerializeObject(bar,
    new JsonSerializerSettings {ContractResolver = new MyTypeContractResolver<Bar>()});

答案 2 :(得分:5)

您可以简单地覆盖派生类中的ParentId

public new int ParentId
{
    get { return base.ParentId; }
    set { base.ParentId = value; }
}

答案 3 :(得分:4)

我通过在派生类的属性上使用new关键字解决了同样的问题。

public class Foo
{
    [JsonIgnore]
    public int ParentId { get; set; }
}

public class Bar: Foo
{
    [JsonProperty("ParentId")]
    public new int ParentId { get; set; }
}

答案 4 :(得分:1)

我用ghost属性解决了同样的问题:

public class Foo
{
    [JsonIgnore]
    public int ParentId { get; set; }

    [NotMapped]
    public int FooParent { get; set; }
}

当我想要显示此属性时,我总是隐藏它,我填充它,其他时候它是null:

Foos.ForEach(x => x.FooParent = ParentId);