通过反射动态 json 序列化过滤
Dynamic json serialization filtering via reflection
我想为 json.net 创建一个动态合同解析器,它将在 运行 时间内排除字段。这个想法是传递给构造函数 something 这将排除 CreateProperties 覆盖中的某些字段。
到目前为止,我想出了传递 PropertyInfo[]
依赖于 Json / Class 属性名称相等性,这在 long 运行 中不好(即我想要将 json 属性 名称覆盖为更短的名称)。解决方案的另一个问题是我需要通过 PropertyInfo[]
,这在我看来并不直观。
也许有一种方法可以使用 LINQ 表达式以更好的方式重写此 class。例如传递 List<Func<T,TOut>>
然后通过反射编译和提取参数。它将更加动态,但不会解决 Json / Class 属性 名称相等的问题。
任何建议,我卡住了....
public class DynamicContractResolver : DefaultContractResolver
{
private readonly PropertyInfo[] m_propertiesExclusion;
public DynamicContractResolver(PropertyInfo[] propertiesExclusion)
{
m_propertiesExclusion = propertiesExclusion;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> jsonProperties = base.CreateProperties(type, memberSerialization);
IEnumerable<string> filteredOutProperties = m_propertiesExclusion.Select(i => i.Name);
jsonProperties = jsonProperties
.Where(i => !filteredOutProperties.Contains(i.PropertyName))
.ToList();
return jsonProperties;
}
}
这是一个采用任意数量 Expression<Func<T, object>>
并排除它们引用的属性的实现。从表达式中提取 属性 名称的代码取自 this answer.
public class DynamicContractResolver<T> : DefaultContractResolver
{
private readonly HashSet<string> propertiesToExclude;
public DynamicContractResolver(
params Expression<Func<T, object>>[] propertyExpressions)
{
this.propertiesToExclude = new HashSet<string>();
foreach (Expression<Func<T, object>> expression in propertyExpressions)
{
string propertyName = GetPropertyNameFromExpression(expression);
this.propertiesToExclude.Add(propertyName);
}
}
protected override IList<JsonProperty> CreateProperties(
Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> jsonProperties =
base.CreateProperties(type, memberSerialization);
if (typeof(T).IsAssignableFrom(type))
{
jsonProperties = jsonProperties
.Where(pr => !this.propertiesToExclude.Contains(pr.PropertyName))
.ToList();
}
return jsonProperties;
}
//
private string GetPropertyNameFromExpression(
Expression<Func<T, object>> expression)
{
MemberExpression body = expression.Body as MemberExpression;
if (body == null)
{
UnaryExpression ubody = (UnaryExpression)expression.Body;
body = ubody.Operand as MemberExpression;
}
return body.Member.Name;
}
}
这是一个使用它的例子:
var resolver = new DynamicContractResolver<MyClass>(
mc => mc.MyIntegerProperty,
mc => mc.MyBoolProperty);
var myClass = new MyClass
{
MyIntegerProperty = 4,
MyStringProperty = "HELLO",
MyBoolProperty = true
};
var settings = new JsonSerializerSettings
{
ContractResolver = resolver,
Formatting = Newtonsoft.Json.Formatting.Indented
};
string serialized = JsonConvert.SerializeObject(
myClass, settings);
Console.WriteLine(serialized);
我想为 json.net 创建一个动态合同解析器,它将在 运行 时间内排除字段。这个想法是传递给构造函数 something 这将排除 CreateProperties 覆盖中的某些字段。
到目前为止,我想出了传递 PropertyInfo[]
依赖于 Json / Class 属性名称相等性,这在 long 运行 中不好(即我想要将 json 属性 名称覆盖为更短的名称)。解决方案的另一个问题是我需要通过 PropertyInfo[]
,这在我看来并不直观。
也许有一种方法可以使用 LINQ 表达式以更好的方式重写此 class。例如传递 List<Func<T,TOut>>
然后通过反射编译和提取参数。它将更加动态,但不会解决 Json / Class 属性 名称相等的问题。
任何建议,我卡住了....
public class DynamicContractResolver : DefaultContractResolver
{
private readonly PropertyInfo[] m_propertiesExclusion;
public DynamicContractResolver(PropertyInfo[] propertiesExclusion)
{
m_propertiesExclusion = propertiesExclusion;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> jsonProperties = base.CreateProperties(type, memberSerialization);
IEnumerable<string> filteredOutProperties = m_propertiesExclusion.Select(i => i.Name);
jsonProperties = jsonProperties
.Where(i => !filteredOutProperties.Contains(i.PropertyName))
.ToList();
return jsonProperties;
}
}
这是一个采用任意数量 Expression<Func<T, object>>
并排除它们引用的属性的实现。从表达式中提取 属性 名称的代码取自 this answer.
public class DynamicContractResolver<T> : DefaultContractResolver
{
private readonly HashSet<string> propertiesToExclude;
public DynamicContractResolver(
params Expression<Func<T, object>>[] propertyExpressions)
{
this.propertiesToExclude = new HashSet<string>();
foreach (Expression<Func<T, object>> expression in propertyExpressions)
{
string propertyName = GetPropertyNameFromExpression(expression);
this.propertiesToExclude.Add(propertyName);
}
}
protected override IList<JsonProperty> CreateProperties(
Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> jsonProperties =
base.CreateProperties(type, memberSerialization);
if (typeof(T).IsAssignableFrom(type))
{
jsonProperties = jsonProperties
.Where(pr => !this.propertiesToExclude.Contains(pr.PropertyName))
.ToList();
}
return jsonProperties;
}
//
private string GetPropertyNameFromExpression(
Expression<Func<T, object>> expression)
{
MemberExpression body = expression.Body as MemberExpression;
if (body == null)
{
UnaryExpression ubody = (UnaryExpression)expression.Body;
body = ubody.Operand as MemberExpression;
}
return body.Member.Name;
}
}
这是一个使用它的例子:
var resolver = new DynamicContractResolver<MyClass>(
mc => mc.MyIntegerProperty,
mc => mc.MyBoolProperty);
var myClass = new MyClass
{
MyIntegerProperty = 4,
MyStringProperty = "HELLO",
MyBoolProperty = true
};
var settings = new JsonSerializerSettings
{
ContractResolver = resolver,
Formatting = Newtonsoft.Json.Formatting.Indented
};
string serialized = JsonConvert.SerializeObject(
myClass, settings);
Console.WriteLine(serialized);