2015-02-23 51 views
8

我使用Newtonsoft's JsonSerializer来连续化一些类。我如何“un-JsonIgnore”派生类中的属性?

因为我想忽略我的序列化过程类的一个领域,我宣布它如下:

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

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

我一直在浏览文档,并在互联网上的方式来覆盖子类中的这种设置(我想我需要像[JsonStopIgnore],但我找不到任何关闭)。


  • 有什么办法,我强迫JsonSerializer再次拿起这个属性?
  • 是否有可能在基类中明确标记属性为[JsonIgnore],但只有

回答

7

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

感谢您对ContractResolver的解释!如果我找不到更轻的解决方案,我会采用这种方式,至少可以进行严格的定制。 – PLNech 2015-02-23 13:37:16

+1

@PLNech当然可以。这绝对是“最重的”解决方案,但我认为它也是使用Json.NET处理它的“正确”方式。 – 2015-02-23 13:39:04

+1

我很感激我现在有一个对“正确”方式的引用,如果我发现自己无法使用“懒惰”方式:P – PLNech 2015-02-23 13:40:51

3

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

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

但请注意,对基础类的任何投射都将授予对隐藏属性的访问权限! – 2015-02-23 13:02:41

+1

@AndreasNiedermair是的。但我认为,在使用Newtonsoft JSonSerializer进行序列化和反序列化时,它应该可以工作。对于剩余的代码,如果该属性被绕过,那么可以。 – xanatos 2015-02-23 13:05:37

9

只有这样,才能“覆盖”的[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

+0

感谢您对我一无所知的机制的解释! 尽管有点沉重,但这可能比使用自定义合约解析器实现相同结果更简单的解决方案:) – PLNech 2015-02-24 09:31:17

+1

没问题;乐意效劳。 – 2015-02-24 16:30:51

2

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

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

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

谢谢,很高兴知道这是可能的。 – PLNech 2016-03-18 16:42:41

+0

我不知道为什么这个工作,但它确实。 我使用mongoDb保存对象后,现在抛出我的映射错误... – bonitzenator 2016-11-16 11:11:38

1

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

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

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

当我想告诉这个属性相当总是隐藏,我填充它,其他时间为空:

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