JSON.NET附带了[JsonIgnore]
和[JsonProperty]
等属性。
我想创建一些自定义的,当串行化运行时运行。[JsonIgnoreSerialize]
或[JsonIgnoreDeserialize]
我将如何扩展框架以包括这一点?
您可以编写类似的自定义合同解析程序
public class MyContractResolver<T> : Newtonsoft.Json.Serialization.DefaultContractResolver
where T : Attribute
{
Type _AttributeToIgnore = null;
public MyContractResolver()
{
_AttributeToIgnore = typeof(T);
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var list = type.GetProperties()
.Where(x => !x.GetCustomAttributes().Any(a => a.GetType() == _AttributeToIgnore))
.Select(p => new JsonProperty()
{
PropertyName = p.Name,
PropertyType = p.PropertyType,
Readable = true,
Writable = true,
ValueProvider = base.CreateMemberValueProvider(p)
}).ToList();
return list;
}
}
您可以像一样在序列化/反序列化中使用它
var json = JsonConvert.SerializeObject(
obj,
new JsonSerializerSettings() {
ContractResolver = new MyContractResolver<JsonIgnoreSerialize>()
});
var obj = JsonConvert.DeserializeObject<SomeType>(
json,
new JsonSerializerSettings() {
ContractResolver = new MyContractResolver<JsonIgnoreDeserialize>()
});
由于您的目标是忽略序列化而不是反序列化的属性,因此可以使用ContractResolver
。
请注意,下面的类正是这样做的,并且是基于CamelCasePropertyNamesContractResolver
的,以确保它序列化为大小写为骆驼形的Json字段。如果您不希望这样,您可以让它从DefaultContractResolver
继承。
此外,我自己的例子是基于字符串的名称,但您可以很容易地检查属性是否由自定义属性装饰,而不是比较属性名称。
public class CamelCaseIgnoringPropertyJsonResolver<T> : CamelCasePropertyNamesContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
// list the properties to ignore
var propertiesToIgnore = type.GetProperties()
.Where(x => x.GetCustomAttributes().OfType<T>().Any());
// Build the properties list
var properties = base.CreateProperties(type, memberSerialization);
// only serialize properties that are not ignored
properties = properties
.Where(p => propertiesToIgnore.All(info => info.Name != p.UnderlyingName))
.ToList();
return properties;
}
}
然后,您可以按如下方式使用它:
static private string SerializeMyObject(object myObject)
{
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCaseIgnoringPropertyJsonResolver<JsonIgnoreSerializeAttribute>()
};
var json = JsonConvert.SerializeObject(myObject, settings);
return json;
}
最后,自定义属性可以是任何类型,但要与示例相匹配:
internal class JsonIgnoreSerializeAttribute : Attribute
{
}
该方法经过测试,也适用于嵌套对象。
不确定这是否是新的,但我建议使用直接处理成员信息的方法GetSerializableMembers
。这样,就可以避免与JsonProperty打交道。
public class MyJsonContractResolver : DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
return base.GetSerializableMembers(objectType)
.Where(mi => mi.GetCustomAttribute<JsonIgnoreSerializeAttribute>() != null)
.ToList();
}
}