我如何 "un-JsonIgnore" 派生 class 中的属性?
How can I "un-JsonIgnore" an attribute in a derived class?
我正在使用 Newtonsoft's JsonSerializer 来序列化一些 classes。
因为我想在序列化过程中省略我的 class 的一个字段,我声明如下:
[JsonIgnore]
public int ParentId { get; set; }
这行得通,但我现在面临一个新问题:在派生的 class 中,我希望该字段出现(并且这样做 only具体派生class).
我一直在浏览文档和在 Internet 上寻找在子 classes 中覆盖此设置的方法(我想我需要类似 [JsonStopIgnore]
的东西,但我找不到任何接近的东西)。
- 有什么办法可以强制
JsonSerializer
重新拾取这个属性吗?
- 是否可以将属性显式标记为
[JsonIgnore]
,但 仅 在基础 class 中?
您可以简单地在派生的 class 中覆盖 ParentId
。
public new int ParentId
{
get { return base.ParentId; }
set { base.ParentId = value; }
}
您可以通过创建自定义 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);
在我们的例子中意味着 "you should serialize only if they are not of type Foo
"(因为 Foo 是 DeclaryingType
)。
然后当你想反序列化时,你将合同解析器的实例传递给 JsonSerializerSettings
:
var bar = new Bar();
var result = JsonConvert.SerializeObject(bar,
new JsonSerializerSettings {ContractResolver = new MyTypeContractResolver<Bar>()});
"override" [JsonIgnore]
属性的行为的唯一方法是使用合同解析器,正如@Yuval Itzchakov 在他的回答中很好地解释的那样。
但是,还有另一种可能对您有用的解决方案:您可以在 classes 中实现 ShouldSerializeParentId()
方法来控制是否使用 [JsonIgnore]
属性,而不是使用 [JsonIgnore]
属性。 ParentId
属性 被序列化。在基础 class 中,使此方法 return false
;然后,将派生的 class 中的方法覆盖为 return 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;
}
}
Fiddle: https://dotnetfiddle.net/65sCSz
我通过在派生 class 的 属性 上使用 new 关键字解决了同样的问题。
public class Foo
{
[JsonIgnore]
public int ParentId { get; set; }
}
public class Bar: Foo
{
[JsonProperty("ParentId")]
public new int ParentId { get; set; }
}
我用ghost解决了同样的问题属性 :
public class Foo
{
[JsonIgnore]
public int ParentId { get; set; }
[NotMapped]
public int FooParent { get; set; }
}
当我想显示这个 属性 时总是隐藏,我填充它,其他时候它是 null :
Foos.ForEach(x => x.FooParent = ParentId);
我正在使用 Newtonsoft's JsonSerializer 来序列化一些 classes。
因为我想在序列化过程中省略我的 class 的一个字段,我声明如下:
[JsonIgnore]
public int ParentId { get; set; }
这行得通,但我现在面临一个新问题:在派生的 class 中,我希望该字段出现(并且这样做 only具体派生class).
我一直在浏览文档和在 Internet 上寻找在子 classes 中覆盖此设置的方法(我想我需要类似 [JsonStopIgnore]
的东西,但我找不到任何接近的东西)。
- 有什么办法可以强制
JsonSerializer
重新拾取这个属性吗? - 是否可以将属性显式标记为
[JsonIgnore]
,但 仅 在基础 class 中?
您可以简单地在派生的 class 中覆盖 ParentId
。
public new int ParentId
{
get { return base.ParentId; }
set { base.ParentId = value; }
}
您可以通过创建自定义 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);
在我们的例子中意味着 "you should serialize only if they are not of type Foo
"(因为 Foo 是 DeclaryingType
)。
然后当你想反序列化时,你将合同解析器的实例传递给 JsonSerializerSettings
:
var bar = new Bar();
var result = JsonConvert.SerializeObject(bar,
new JsonSerializerSettings {ContractResolver = new MyTypeContractResolver<Bar>()});
"override" [JsonIgnore]
属性的行为的唯一方法是使用合同解析器,正如@Yuval Itzchakov 在他的回答中很好地解释的那样。
但是,还有另一种可能对您有用的解决方案:您可以在 classes 中实现 ShouldSerializeParentId()
方法来控制是否使用 [JsonIgnore]
属性,而不是使用 [JsonIgnore]
属性。 ParentId
属性 被序列化。在基础 class 中,使此方法 return false
;然后,将派生的 class 中的方法覆盖为 return 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;
}
}
Fiddle: https://dotnetfiddle.net/65sCSz
我通过在派生 class 的 属性 上使用 new 关键字解决了同样的问题。
public class Foo
{
[JsonIgnore]
public int ParentId { get; set; }
}
public class Bar: Foo
{
[JsonProperty("ParentId")]
public new int ParentId { get; set; }
}
我用ghost解决了同样的问题属性 :
public class Foo
{
[JsonIgnore]
public int ParentId { get; set; }
[NotMapped]
public int FooParent { get; set; }
}
当我想显示这个 属性 时总是隐藏,我填充它,其他时候它是 null :
Foos.ForEach(x => x.FooParent = ParentId);