Как мне спроектировать мой перезагруженный API для приема данных через POST в разных форматах (JSON, CSV) для той же цели? - PullRequest
2 голосов
/ 02 мая 2019

У меня есть бизнес-требование, чтобы разработать перезагруженный API с использованием Spring boot, который выполняет следующее: -

a) Примите данные транспортного средства в формате csv по запросу POST от клиента. б) Примите данные транспортного средства в формате JSON через POST-запрос от клиента.

В вышеприведенных а) и б) поля одинаковы, но только в разных форматах (одно - JSON, а другое - CSV).

Мой вопрос: каким должен быть мой дизайн, чтобы добиться этого?

1) Должен ли я просто создать класс А и иметь 2 разных метода конечной точки. Один принять CSV, а другой принять JSON? Или есть более эффективные способы борьбы с такими сценариями?

2) Как должна выглядеть структура моего класса?

3) Какие-либо конкретные шаблоны дизайна, которые соответствуют этому требованию? Или какие-то конкретные рекомендации для решения такого сценария?

Любая помощь высоко ценится.

1 Ответ

1 голос
/ 02 мая 2019

Вы можете сделать это, определив интерфейс Deserializer и различные реализации для каждого формата.

К вопросу 1: Это зависит от того, как вы хотите это сделать. Один из способов - использовать одну конечную точку и использовать заголовок Content-Type веб-запроса и выбрать десериализатор на его основе.

Вот пример:

public enum Formats { JSON, CSV, XML }

public interface Deserializer {

  Format getFormat();
  object deserialize(string input);
}

public JSONDeserializer extends Deserializer {

    public Format getFormat() { return Formats.JSON; }
    public object deserialize(string input) { .... }
}

public CSVDeserializer extends Deserializer {
    public Format getFormat() { return Formats.CSV; }
    public object deserialize(string input) { .... }
}

public XMLDeserializer extends Deserializer {
    public Format getFormat() { return Formats.XML; }
    public object deserialize(string input) { .... }
}

Если вы хотите избежать явного перечисления Format для определения ваших типов, вы можете использовать тип содержимого напрямую как string или MediaType. Это приведет к тому, что ваш интерфейс Deserializer будет тесно связан с вашими обработчиками запросов, что затруднит их использование в других частях кода. Также в качестве альтернативного дизайна вы можете перенести ответственность за проверку в десериализаторе.

public interface Deserializer {

  string getContentType();
  object deserialize(string input);
}

public JSONDeserializer extends Deserializer {

    public string getContentType() {
        return "application/json";
    }

    public object deserialize(string input) { .... }
}

public interface Deserializer {

  bool cetDeserialize(string contentType);
  object deserialize(string input);
}

public JSONDeserializer extends Deserializer {

    public bool cetDeserialize(string contentType) {
       return contentType == "application/json";
    }

    public object deserialize(string input) { .... }
}

Вот как вы его используете.

List<String> mDeserializers = Arrays.asList(
    new JSONDeserializer(), 
    new CSVDeserializer(), 
    new XMLNDeserializer()
);

Deserializer deserializer = mDeserializers
      .stream()
      .filter(d => d.getContentType() == contentType)
      .findFirst();

// or if you use a specific format:
Deserializer deserializer = mDeserializers
      .stream()
      .filter(d => d.getFormat() == getFormatFromContentType(contentType))
      .findFirst();

deserializer.deserialize(input);

Что касается весны, не пробовал сам, вы можете сделать что-то вроде этого, не указывая расход:

 @RequestMapping(value = "/data", method = RequestMethod.POST)
 public String process(
   @RequestHeader HttpHeaders httpHeaders, 
   @RequestBody String body){
   // get value of content-type header as string
   // get serializer based on string value
 }

или

 @RequestMapping(value = "/data", method = RequestMethod.POST)
 public String process(
   @RequestHeader(value="Content-Type") String contentType, 
   @RequestBody String body){
   // get serializer based on string value
 }
...