正如 Lasse Karlsen 在 cmets 中指出的,如果您的 SharedClass 没有对其父类的引用,则该类中的 ShouldSerializeSomeValue() 方法无法知道父类是什么。
但是,如果您使用的是Json.Net 6.0 Release 6 或更高版本,则可以通过使用自定义JsonConverter 作为有选择地省略共享类中的属性(而不是使用ShouldSerialize() 方法)的方法来解决此问题,并且然后将 [JsonConverter] 属性放在相应父类中的 SharedClass 属性上,以指示该实例应省略哪些属性。
这是更新后的示例类定义的外观。你会注意到我在Foo 上标记了SharedClass 实例,表明它应该使用一个名为OmitPropertiesConverter 的自定义转换器来省略SomeValue 属性。 Bar 上的 SharedClass 实例不使用转换器,因此该实例将正常序列化。
class Foo
{
[JsonConverter(typeof(OmitPropertiesConverter), "SomeValue")]
public SharedClass Shared { get; set; }
}
class Bar
{
public SharedClass Shared { get; set; }
}
class SharedClass
{
public string SomeValue { get; set; }
public string SomeOtherValue { get; set; }
}
下面是OmitPropertiesConverter 的代码。它的构造函数接受一个propsToOmit 字符串,该字符串是以逗号分隔的要从序列化中排除的属性名称列表。这将被拆分为一个数组,供以后在WriteJson 方法中使用。 WriteJson 方法采用 SharedClass 值,将其转换为 JObject,然后以编程方式删除 propsToOmit 数组中的属性,然后将 JObject 写入 JsonWriter。
class OmitPropertiesConverter : JsonConverter
{
string[] propsToOmit;
public OmitPropertiesConverter(string propsToOmit)
{
this.propsToOmit = propsToOmit.Split(new char[] {','},
StringSplitOptions.RemoveEmptyEntries);
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(SharedClass));
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
JObject jo = JObject.FromObject(value, serializer);
// Note: ToList() is needed here to prevent "collection was modified" error
foreach (JProperty prop in jo.Properties()
.Where(p => propsToOmit.Contains(p.Name))
.ToList())
{
prop.Remove();
}
jo.WriteTo(writer);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
这是一个简单的演示程序,展示了转换器的实际运行情况:
class Program
{
static void Main(string[] args)
{
var root = new
{
Foo = new Foo
{
Shared = new SharedClass
{
SomeValue = "foo1",
SomeOtherValue = "foo2"
}
},
Bar = new Bar
{
Shared = new SharedClass
{
SomeValue = "bar1",
SomeOtherValue = "bar2"
}
}
};
string json = JsonConvert.SerializeObject(root, Formatting.Indented);
Console.WriteLine(json);
}
}
这是上面演示的输出。您会注意到,Foo 内的 SharedClass 实例上的 SomeValue 属性未包含在输出中,但它包含在 Bar 内的实例中。
{
"Foo": {
"Shared": {
"SomeOtherValue": "foo2"
}
},
"Bar": {
"Shared": {
"SomeValue": "bar1",
"SomeOtherValue": "bar2"
}
}
}