JSON.NET附带了[JsonIgnore]
和[JsonProperty]
等属性属性。
我想创建一些在序列化运行时运行的自定义项,例如
[JsonIgnoreSerialize]
或[JsonIgnoreDeserialize]
我如何扩展框架以包含此内容?
答案 0 :(得分:9)
您可以像这样编写自定义合约解析程序
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>()
});
答案 1 :(得分:3)
由于您的目标是忽略序列化但不反序列化的属性,因此您可以使用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
{
}
该方法经过测试,也适用于嵌套对象。
答案 2 :(得分:0)
不知道这是否是新的,但我建议使用直接处理成员信息的方法GetSerializableMembers
。这样,就可以避免不得不处理JsonProperty。
public class MyJsonContractResolver : DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
return base.GetSerializableMembers(objectType)
.Where(mi => mi.GetCustomAttribute<JsonIgnoreSerializeAttribute>() != null)
.ToList();
}
}