Как создать один класс модели для использования с несколькими методами API, требующими разных JSON полезных нагрузок? - PullRequest
1 голос
/ 18 марта 2020

У меня есть несколько API под одним сервисом. API принимают разные JSON полезные нагрузки. Я хочу создать один класс модели с атрибутами и значениями и установить их. Может ли это быть достигнуто с помощью одного модельного класса для нескольких API? Например, у меня есть один метод API, который принимает идентификатор и имя JSON, и другой API, который принимает идентификатор пользователя и цвет. Как я могу указать, какие конкретные c атрибуты и значения следует применять при отправке запроса в конкретный c API, который требует эти данные? Я использую JsonConvert.SerializeObject(Model) в своем запросе на отправку.

В настоящее время у меня есть следующее в моей модели. Я использую экземпляр класса TagModel, присваиваю значения, но при использовании SerializeForApiMethod и указании, какой метод мне нужен, указав c значения, он принимает все назначенные значения модели. Я пытаюсь просто извлечь те, которые мне нужны, с указанием c имени метода.

 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"));      
        }

Сложная полезная нагрузка

enter image description here

1 Ответ

0 голосов
/ 19 марта 2020

Вы можете выборочно включать или исключать свойства во время сериализации, используя пользовательские ContractResolver. Вы можете ввести пользовательский атрибут, чтобы указать, какие свойства в вашей модели должны быть включены в какие методы API. Затем пусть распознаватель ищет эти атрибуты и игнорирует свойства модели, которые не соответствуют методу API, для которого вы сериализуете.

Код атрибута:

[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 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; }
}

Наконец, создайте вспомогательный метод, который использует преобразователь для сериализации модели:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...