如何“un-JsonIgnore”派生类中的属性?

问题描述 投票:0回答:6

我正在使用 Newtonsoft 的 JsonSerializer 来序列化一些类。

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

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

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

我一直在浏览文档和互联网,寻找一种在子类中覆盖此设置的方法(我想我需要类似

[JsonStopIgnore]
的东西,但我找不到任何接近的东西)。


  • 有什么办法可以让我强制
    JsonSerializer
    重新拾取这个属性吗?
  • 是否可以将属性显式标记为
    [JsonIgnore]
    ,但仅在基类中标记为
c# .net json json.net jsonserializer
6个回答
18
投票
“覆盖”

[JsonIgnore]

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

但是,还有另一种可能适合您的解决方案:您可以在类中实现

[JsonIgnore]

 方法来控制 
ShouldSerializeParentId()
 属性是否被序列化,而不是使用 
ParentId
 属性。  在基类中,让这个方法返回
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; } }

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

您可以通过创建自定义

14
投票
并覆盖其

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 关键字解决了同样的问题。

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

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

6
投票

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

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

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

当我想显示这个始终隐藏的属性时,我会填充它,其他时候它为空:

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

另一种方法是定义一个支持成员变量,然后序列化该支持变量:

0
投票
public class Foo { [JsonIgnore] public int ParentId { get; set; } } public class Bar: Foo { [JsonProperty("_parentId")] private int _parentId; public int ParentId { get { return _parentId; } set { _parentId = value; } } }


© www.soinside.com 2019 - 2024. All rights reserved.