【问题标题】:Dynamic json serialization filtering via reflection通过反射进行动态 json 序列化过滤
【发布时间】:2015-02-19 12:23:33
【问题描述】:

我想为 json.net 创建一个动态合约解析器,它将在运行时排除字段。这个想法是传递给构造函数 something ,它将排除 CreateProperties 覆盖中的某些字段。

到目前为止,我想出了传递 PropertyInfo[] 的方法,它依赖于 Json / Class 属性名称相等性,从长远来看这是不好的(即,我想将 json 属性名称覆盖为更短的名称)。解决方案的另一个问题是我需要传递PropertyInfo[],这在我看来并不直观。

也许有一种方法可以使用 LINQ 表达式以更好的方式重写这个类。例如像传递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;
    }
}

【问题讨论】:

  • 这里是否使用[JsonIgnore] 属性选项?
  • @AndrewWhitaker 很遗憾没有,因为我有时需要展示,有时需要隐藏......
  • 这对于单一类型来说相当简单。这是目标用途还是您要从多种类型中排除属性?
  • @AndrewWhitaker 我有一个来自 DB 的类型,有时我需要它部分,有时我需要它完整。由于序列化结果保存到缓存中,我想在序列化之前排除或包含。

标签: c# .net serialization json.net


【解决方案1】:

这是一个实现,它采用任意数量的Expression&lt;Func&lt;T, object&gt;&gt;s 并排除它们引用的属性。从表达式中提取属性名称的代码取自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;
    }

    // https://stackoverflow.com/a/2916344/497356
    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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 2012-08-31
    • 2013-07-10
    • 2021-08-22
    相关资源
    最近更新 更多