【发布时间】:2018-12-11 04:00:43
【问题描述】:
是否有一个属性告诉 json.net 忽略一个类的所有属性但包括所有字段(不管访问修饰符)?
如果没有,有没有办法创建一个?
基本上,我想要一个装饰类的属性,它与将[JsonIgnore] 放在每个属性的前面具有相同的效果。
【问题讨论】:
是否有一个属性告诉 json.net 忽略一个类的所有属性但包括所有字段(不管访问修饰符)?
如果没有,有没有办法创建一个?
基本上,我想要一个装饰类的属性,它与将[JsonIgnore] 放在每个属性的前面具有相同的效果。
【问题讨论】:
如果你用[JsonObject(MemberSerialization.Fields)] 标记你的班级,那将让你大部分时间到达那里。此属性告诉 Json.Net 您希望它序列化类中的所有字段,而不考虑访问修饰符,但不考虑属性。
但是,如果您的类中有任何自动属性(即使用 { get; set; } 声明的那些),那么此属性将导致编译器生成的支持字段也被序列化,这可能是您不想要的。要抑制这些,您需要使用自定义IContractResolver。您可以通过从DefaultContractResolver 继承并覆盖CreateProperty 方法来创建一个。在该方法中,检查该类是否应用了[JsonObject(MemberSerialization.Fields)] 属性,如果是,则检查该成员是否是编译器生成的字段。如果是,则将其设置为忽略。
class CustomResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
JsonObjectAttribute attr = prop.DeclaringType.GetCustomAttribute<JsonObjectAttribute>();
if (attr != null && attr.MemberSerialization == MemberSerialization.Fields &&
member.GetCustomAttribute<CompilerGeneratedAttribute>() != null)
{
prop.Ignored = true;
}
return prop;
}
}
要使用解析器,您需要通过JsonSerializerSettings 将其传递给SerializeObject 方法:
var settings = new JsonSerializerSettings
{
ContractResolver = new CustomResolver(),
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(yourObject, settings);
这是一个概念证明:https://dotnetfiddle.net/aNXWbn
【讨论】:
您可以创建一个自定义 IContractResolver 并决定根据您创建的 custom attribute 进行序列化:
public class IgnorePropertyResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
//Todo: Check your custom attribute. You have MemberInfo here to navigate to your class and GetCustomAttributes<>
//e.g: property.ShouldSerialize = member.DeclaringType.GetCustomAttribute<JsonIgnoreAllProperties>() == null;
property.ShouldSerialize = false;
return property;
}
}
然后你需要将它注册为默认,这取决于你的环境。或者你直接使用它,那么你甚至不需要一个属性:
string json =
JsonConvert.SerializeObject(
product,
Formatting.Indented,
new JsonSerializerSettings
{
ContractResolver = new IgnorePropertyResolver()
}
);
public class JsonIgnoreAllPropertiesAttribute : Attribute
{
}
并使用:
[JsonIgnoreAllProperties]
public class ClassToSerialize
{
public int Ignored { get;set; }
public int Serialized;
}
【讨论】:
[JsonIgnoreAllProperties]@kofifus
您可以将[JsonObject(MemberSerialization.OptIn)] 属性添加到您的班级,然后所有内容都将被忽略,除非您通过在成员上使用[JsonProperty] 属性明确选择加入。
[JsonObject(MemberSerialization.OptIn)]
public class Address
{
[JsonProperty]
private string _field1 = "bob";
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
}
例如
using System;
using AutoFixture;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var fixture = new Fixture();
var address = fixture.Create<Address>(); // Create an address filled with junk
var json = JsonConvert.SerializeObject(address);
Console.WriteLine(json);
}
}
将输出:
{"_field1":"bob"}
【讨论】: