如何在派生类中"un-JsonIgnore"属性?



我正在使用Newtonsoft的JsonSerializer串行化一些类。

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

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

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

我一直在查阅文档和互联网,寻找在子类中覆盖此设置的方法(我想我需要类似[JsonStopIgnore]的东西,但找不到任何接近的东西)。


  • 有什么办法可以让JsonSerializer重新获取这个属性吗
  • 是否可以显式地将属性标记为[JsonIgnore],但在基类中仅

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

但是,还有另一种可能的解决方案:您可以在类中实现ShouldSerializeParentId()方法来控制ParentId属性是否序列化,而不是使用[JsonIgnore]属性。在基类中,使该方法返回false;然后,重写派生类中的方法以返回true。(这个特性在Json.Net中被称为条件属性序列化。)

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;
    }
}

Fiddle:https://dotnetfiddle.net/65sCSz

您可以通过创建自定义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>()});

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

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

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

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

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

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

当我想显示这个总是隐藏的属性时,我填充它,其他时候它是空的:

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

相关内容

  • 没有找到相关文章

最新更新