Как я могу сделать RequestParam динамическим?

У меня есть список POST запросов, где тела запросов очень похожи

{
  "entity":{
             "type":"Nissan"
             "parts":{
                     "Nissan_unique_content1":"value",
                     "Nissan_unique_content2":"value"
                   }
           }
  "updateDate":"Date..."
}
{
  "entity":{
             "type":"Ford"
             "parts":{
                     "Ford_unique_content1":"value",
                     "Ford_unique_content2":"value",
                     "Ford_unique_content3":"value"
                   }
           }
  "updateDate":"Date..."
}

У меня универсал RequestBody

public class RequestBody<T>{
  EntityBody<T> entity;
  Date updateDate;
}

public class EntityBody<T>{
  String type;
  T parts;
}

В моем посте Controller у меня есть метод как

@RequestMapping(value = "/{type}")
public ResponseEntity<?> create(
            @PathVariable(value = "type") String type,
            @RequestBody RequestBody<T> body) {
...
}

В любом случае, общий тип T может быть назначен в зависимости от типа? В этом случае мне не нужно было бы создавать несколько методов создания, иначе мне нужно создать несколько методов, например

@RequestMapping(value = "/nissan")
public ResponseEntity<?> createNissan(
            @RequestBody RequestBody<NissanContent> body) {
...
}

@RequestMapping(value = "/ford")
public ResponseEntity<?> createFord(
            @RequestBody RequestBody<Ford> body) {
...
}

какие ненужные повторы.

Вы можете использовать jackson для сопоставления json с объектами (baeldung.com/jackson-inheritance). На стороне java вы можете использовать шаблон посетителя.

Andrey 19.02.2019 23:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
417
2

Ответы 2

Это можно сделать с помощью аннотации @JsonTypeInfo.

Например:

Определите объекты в соответствии с различными структурами под ключом «части»:

class NissanParams {

  @JsonProperty("Nissan_unique_content1")
  private String nissanUniqueContent1;

  @JsonProperty("Nissan_unique_content2")
  private String nissanUniqueContent2;

  // getters + setters

}

В EntityBody удалите поле type и добавьте аннотации:

public class EntityBody<T> {

  @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
  @JsonSubTypes({ @JsonSubTypes.Type(value = NissanParams.class, name = "Nissan")})
  private T parts;

}

И будет один метод контроллера:

@PostMapping(path = "{make}",
  produces = MediaType.APPLICATION_JSON_VALUE,
  consumes = MediaType.APPLICATION_JSON_VALUE)
public RequestBody<Object> create(@PathVariable("make") String make,
                                 @org.springframework.web.bind.annotation.RequestBody RequestBody<Object> body) {
  // please change the name of "RequestBody" entity, in order to avoid name clash with the annotation
}

Вы можете использовать аннотации JsonTypeInfo и JsonSubTypesJackson. Ваша модель может выглядеть так:

class EntityBody {

    private Car parts;

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
    @JsonSubTypes({
            @JsonSubTypes.Type(name = "Ford", value = Ford.class),
            @JsonSubTypes.Type(name = "Nissan", value = Nissan.class)
    })
    public Car getParts() {
        return parts;
    }
}

Как видите, вам не нужно type имущество. Его прочитает Jackson, чтобы узнать тип автомобиля. Я создал Car базовый класс/интерфейс, но вам не нужно этого делать.

Ваш метод POST может выглядеть так:

@RequestMapping(value = "/cars", method = RequestMethod.POST)
public ResponseEntity<?> create(@RequestBody RequestPayload body) {
    logger.info(body.toString());

    return ResponseEntity.ok("OK");
}

Здесь не нужно PathVariable.

Другие вопросы по теме