本文介绍了如何创建一个模型类以与需要不同 JSON 有效负载的多个 API 方法一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一项服务下有多个 API.API 采用不同的 JSON 有效负载.我想创建一个具有属性和值的模型类并设置它们.这可以通过一个用于多个 API 的模型类来实现吗?例如,我有一个采用 JSON id 和名称的 API 方法和另一个采用用户 ID 和颜色的 API.在将请求发送到需要这些数据的特定 API 时,如何指示要应用哪些特定属性和值?我在发送请求中使用 JsonConvert.SerializeObject(Model).

I have a several APIs under one service. The APIs take different JSON payloads. I want to create one model class with attributes and values and set them. Can this be achieved with one model class to use for the several APIs? For example, I have one API method which takes a JSON id and name and another API that takes userID and color. How can I indicate which specific attritubes and values to apply when sending the request to the specific API that requires those data? I am using JsonConvert.SerializeObject(Model) in my Send request.

目前我的模型中有以下内容.我正在使用 TagModel 类的实例来分配值,但是当使用 SerializeForApiMethod 并说明我需要哪个方法时,它需要分配的整个模型值.我正在尝试使用特定方法名称提取我需要的那些.

Currently I have the following in my model. I am using the instance of the TagModel class the assign the values but when using the SerializeForApiMethod and stating which method I need the specific values it takes entire model values assigned. I am trying to just extract the ones I need with the specific method name.

 public class TagModel
    {

        public static TagModel model = new TagModel
        {
            endpointIds = new List<int> { -2147483612, -2147483611 },
            tagIds = new List<int> { 35, 37 },
            id = -2147483639,
            parentId = 37
        };

        [UseWithApiMethods("UpdateEndpointsToTags")]
        public List<int> endpointIds { get; set; }
        public List<int> tagIds { get; set; }

        [UseWithApiMethods("UpdateEndpointsFromTags")]
         public int id { get; set; }
         public int parentId { get; set; }
    }


This is m helper class:
```public class Helper
    {

        [AttributeUsage(AttributeTargets.Property)]
        public class UseWithApiMethodsAttribute : Attribute
        {
            public UseWithApiMethodsAttribute(params string[] methodNames)
            {
                MethodNames = methodNames;
            }

            public string[] MethodNames { get; private set; }
        }

        public class SelectivePropertyResolver : DefaultContractResolver
        {
            public string ApiMethodName { get; private set; }

            public SelectivePropertyResolver(string apiMethodName)
            {
                ApiMethodName = apiMethodName;
            }

            protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
            {
                JsonProperty prop = base.CreateProperty(member, memberSerialization);
                if (member.MemberType == MemberTypes.Property)
                {
                    var att = ((PropertyInfo)member).GetCustomAttribute<UseWithApiMethodsAttribute>(true);
                    if (att != null && !att.MethodNames.Contains(ApiMethodName))
                    {
                        prop.Ignored = true;
                    }
                }
                return prop;
            }
        }

        public  string SerializeForApiMethod(Object model, string methodName)
        {
            var settings = new JsonSerializerSettings
            {
                ContractResolver = new SelectivePropertyResolver(methodName),
                Formatting = Formatting.Indented
            };
            return JsonConvert.SerializeObject(model, settings);
        }
    }

This is my Method class using the SerializeForApiMethod method
```public HttpWebResponse UpdateEndpointsFromTags()
        {
            RequestHandler requestor = new RequestHandler(BaseUrl + "UpdateEndpointsFromTags", HttpVerb.POST, AuthenticationType.Bearer);
            return requestor.SendRequest(helper.SerializeForApiMethod(model , "UpdateEndpointsFromTags"));
        }

        public HttpWebResponse UpdateEndpointsToTags()
        {
            RequestHandler requestor = new RequestHandler(BaseUrl + "UpdateEndpointsToTags", HttpVerb.POST, AuthenticationType.Bearer);
              return requestor.SendRequest(helper.SerializeForApiMethod(model, "UpdateEndpointsToTags"));
        }

复杂有效载荷

推荐答案

您可以在序列化期间使用自定义 ContractResolver.您可以引入自定义属性来指示模型中的哪些属性应包含在哪些 API 方法中.然后让解析器查找这些属性并忽略与您要序列化的 API 方法不匹配的模型属性.

You can selectively include or exclude properties during serialization using a custom ContractResolver. You could introduce a custom attribute to indicate which properties in your model should be included with which API method(s). Then have the resolver look for those attributes and ignore the model properties that don't match the API method for which you are serializing.

属性代码:

[AttributeUsage(AttributeTargets.Property)]
public class UseWithApiMethodsAttribute : Attribute
{
    public UseWithApiMethodsAttribute(params string[] methodNames)
    {
        MethodNames = methodNames;
    }

    public string[] MethodNames { get; private set; }
}

解析器代码:

public class SelectivePropertyResolver : DefaultContractResolver
{
    public string ApiMethodName { get; private set; }

    public SelectivePropertyResolver(string apiMethodName)
    {
        ApiMethodName = apiMethodName;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        if (member.MemberType == MemberTypes.Property)
        {
            var att = ((PropertyInfo)member).GetCustomAttribute<UseWithApiMethodsAttribute>(true);
            if (att == null || !att.MethodNames.Contains(ApiMethodName))
            {
                prop.Ignored = true;
            }
        }
        return prop;
    }
}

然后,使用新属性标记您的模型,例如:

Then, mark up your model with the new attribute like this, for example:

public class Model
{
    [UseWithApiMethods("method1", "method3")]
    public int id { get; set; }

    [UseWithApiMethods("method1")]
    public string name { get; set; }

    [UseWithApiMethods("method2")]
    public int userId { get; set; }

    [UseWithApiMethods("method2")]
    public string color { get; set; }
}

最后,创建一个使用解析器序列化模型的辅助方法:

Finally, create a helper method which uses the resolver to serialize the model:

public static string SerializeForApiMethod(object model, string methodName)
{
    var settings = new JsonSerializerSettings
    {
        ContractResolver = new SelectivePropertyResolver(methodName),
        Formatting = Formatting.Indented
    };
    return JsonConvert.SerializeObject(model, settings);
}

这样称呼,例如:

string json = SerializeForApiMethod(model, "method1");

这是一个工作演示:https://dotnetfiddle.net/vfXCqP

这篇关于如何创建一个模型类以与需要不同 JSON 有效负载的多个 API 方法一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 23:39