根据查询参数条件系列化会员

根据查询参数条件系列化会员

本文介绍了根据查询参数条件系列化会员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想控制从我的模特属性是序列化到我WebAPI2 JSON响应的基础上,查询参数匹配的属性。我主要是想做到这一点,以减少带宽而不会导致视图模型类的增殖的GET。例如:

I would like to control which properties from my model are serialized to my WebAPI2 JSON response, based on matching a query parameter to an attribute. I mainly want to do this to reduce bandwidth on GETs without causing a proliferation of ViewModel classes. For example:

GET /books/1?format=summary

public class Book
{
    [SerializeFormat("summary")]
    public int Id { get; set; }

    [SerializeFormat("summary")]
    public string Title { get; set; }

    public string Contents { get; set; }
}

[SerializeFormat("summary","Id","Title")]
public class Book
{ ... }

要做到这一点我自己,我可以从实施 ISerializable的自定义的基础派生的所有我的模型类。在 ISerializable.GetObjectData(),通过所有属性检查属性迭代。不知道这种想法的性能。

To do this myself, I could derive all of my model classes from a custom base implementing ISerializable. In ISerializable.GetObjectData(), iterate through all properties inspecting the attributes. Not sure about performance on this idea.

不想重塑这个解决方案,但如果它已经存在作为一个包。

Don't want to reinvent this solution, though if it already exists as a package.

推荐答案

一种可能性是引入一个定制的 JsonConditionalIncludeAttribute 可应用于属性和字段:

One possibility would be to introduce a custom attribute JsonConditionalIncludeAttribute that can be applied to properties and fields:

[System.AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
public class JsonConditionalIncludeAttribute : System.Attribute
{
    public JsonConditionalIncludeAttribute(string filterName)
    {
        this.FilterName = filterName;
    }

    public string FilterName { get; private set; }
}

接下来,子类 DefaultContractResolver ,重写 CreateProperty ,并为具有属性返回null至少有一个 [JsonConditionalInclude] 应用,其中没有一个匹配供应合同解析器的一个过滤器:

Next, subclass DefaultContractResolver, override CreateProperty, and return null for properties that have at least one [JsonConditionalInclude] applied, none of which match the a filter supplied to the contract resolver:

public class JsonConditionalIncludeContractResolver : DefaultContractResolver
{
    public JsonConditionalIncludeContractResolver(string filterName)
    {
        this.FilterName = filterName;
    }

    public string FilterName { get; set; }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        // Properties without JsonConditionalIncludeAttribute applied are serialized unconditionally.
        // Properties with JsonConditionalIncludeAttribute are serialized only if one of the attributes
        // has a matching filter name.
        var attrs = property.AttributeProvider.GetAttributes(typeof(JsonConditionalIncludeAttribute), true);
        if (attrs.Count > 0 && !attrs.Cast<JsonConditionalIncludeAttribute>().Any(a => a.FilterName == FilterName))
            return null;
        return property;
    }
}

最后,你的序列化类JSON时,设置 JsonSerializerSettings.ContractResolver 等于您的自定义合同解析器,初始化 FILTERNAME 从您的网络请求,例如:

Finally, when serializing your class to JSON, set JsonSerializerSettings.ContractResolver equal to your custom contract resolver, initializing the FilterName from your web request, for instance:

public class TestClass
{
    public string Property1 { get; set; }

    [JsonConditionalInclude("summary")]
    [JsonConditionalInclude("title")]
    public string Property2 { get; set; }

    [JsonConditionalInclude("summary")]
    public string Property3 { get; set; }

    [JsonConditionalInclude("title")]
    [JsonConditionalInclude("citation")]
    public string Property4 { get; set; }

    [JsonConditionalInclude("citation")]
    public string Field1;

    public static void Test()
    {
        var test = new TestClass { Property1 = "a", Property2 = "b", Property3 = "c", Property4 = "d", Field1 = "e" };
        Test(test, "summary"); // Prints "a", "b" and "c"
        Test(test, "title");   // Prints "a", "b" and "d".
        Test(test, "citation");// Prints "e", "a" and "d"
        Test(test, null);      // Prints "e", "a", "b", "c" and "d".
    }

    public static string Test(TestClass test, string webRequestFormat)
    {
        var settings = new JsonSerializerSettings { ContractResolver = new JsonConditionalIncludeContractResolver(webRequestFormat) };

        var json = JsonConvert.SerializeObject(test, Formatting.Indented, settings);

        Debug.WriteLine(json);
        return json;
    }
}

该合同解析器将适用于所有的类被序列化,而不仅仅是根类,它看起来是你想要的。

The contract resolver will apply to all classes being serialized, not just the root class, which looks to be what you want.

这篇关于根据查询参数条件系列化会员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-26 13:17