我有一个像这样的属性的接口:
public interface IFoo {
// ...
[JsonIgnore]
string SecretProperty { get; }
// ...
}
我希望在序列化所有实现类时忽略SecretProperty
。但似乎我必须在属性的每个实现上定义JsonIgnore
属性。有没有办法实现这一点,而无需为每个实现添加JsonIgnore
属性?我没有找到任何帮助我的序列化设置。
答案 0 :(得分:8)
经过一番搜索后,我发现了这个问题:
How to inherit the attribute from interface to object when serializing it using JSON.NET
我接受了Jeff Sternal的代码并添加了JsonIgnoreAttribute
检测,所以它看起来像这样:
class InterfaceContractResolver : DefaultContractResolver
{
public InterfaceContractResolver() : this(false) { }
public InterfaceContractResolver(bool shareCache) : base(shareCache) { }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
var interfaces = member.DeclaringType.GetInterfaces();
foreach (var @interface in interfaces)
{
foreach (var interfaceProperty in @interface.GetProperties())
{
// This is weak: among other things, an implementation
// may be deliberately hiding an interface member
if (interfaceProperty.Name == member.Name && interfaceProperty.MemberType == member.MemberType)
{
if (interfaceProperty.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Any())
{
property.Ignored = true;
return property;
}
if (interfaceProperty.GetCustomAttributes(typeof(JsonPropertyAttribute), true).Any())
{
property.Ignored = false;
return property;
}
}
}
}
return property;
}
}
在我的InterfaceContractResolver
中使用此JsonSerializerSettings
,所有在任何界面中都有JsonIgnoreAttribute
的属性也会被忽略,即使他们有JsonPropertyAttribute
(由于内部if
块的顺序。)
答案 1 :(得分:2)
我发现创建一个只有我想要的属性的DTO并将该对象序列化为JSON是最简单的。它创建了许多小的,特定于上下文的对象,但是管理代码库更容易,我不必考虑我正在序列化的内容与我忽略的内容。
答案 2 :(得分:1)
在Json.NET的最新版本中,将[JsonIgnore]
应用于接口属性仅能正常工作,并成功地防止它们针对所有实现类型进行序列化。不再需要自定义合同解析器。
例如,如果我们定义以下类型:
public interface IFoo
{
[JsonIgnore]
string SecretProperty { get; set; }
string Include { get; set; }
}
public class Foo : IFoo
{
public string SecretProperty { get; set; }
public string Include { get; set; }
}
然后,以下测试在Json.NET 11和12(以及可能更早的版本)中通过:
var root = new Foo
{
SecretProperty = "Ignore Me",
Include = "Include Me",
};
var json = JsonConvert.SerializeObject(root);
Assert.IsTrue(json == "{\"Include\":\"Include Me\"}");// Passes
演示小提琴here。
我相信Json.NET 4.0.3中已添加了此功能,尽管发行说明中未明确提及JsonIgnore
:
新功能-现在可以将JsonObject和JsonProperty属性放在接口上,并在序列化实现对象时使用。
(该实现可在JsonTypeReflector.GetAttribute<T>(MemberInfo memberInfo)
中找到。)
答案 3 :(得分:-1)
您应该在班级名称前添加[DataContract]
。
它将默认值从包含所有属性更改为仅包括显式标记的属性。之后,在要包含在JSON输出中的每个属性前面添加“[DataMember]”。