Spring @RequestBody без использования pojo? - PullRequest
0 голосов
/ 17 декабря 2018

Я использую Spring Boot, и у меня есть метод, определенный следующим образом в моем контроллере

@PostMapping("/update)
public void update(@RequestBody User user) {
    ...
}

Однако в моем почтовом запросе от клиента (например, веб-интерфейс или почтальон) у меня есть что-то вроде этого:

{
    "firstName" : "John",
    "lastName" : "Doe",
    "id" : 1234,
    "metaInfoId" : "5457sdg26sg4636"
}

Дело в том, что в моем пользовательском pojo есть только firstName, id и lastName полей экземпляра. Однако в моем запросе я have to send metaInfoId, а также для некоторых других нужд.Итак, как я могу получить или разделить metaInfoId и User модель в моем методе контроллера выше?

Нужно ли создавать еще один класс модели с именем UserModelRequest, добавить все поля User вместе с полем metaInfoId и затем использовать @RequestBody?Есть ли способ просто удалить metaInfoId из запроса, а затем взять все остальное и сбросить его в User pojo?Вы можете легко сделать это, например, в nodejs (просто склейте свой объект и возьмите то, что вам нужно).

Так есть ли способ сделать это в Java Spring, не создавая другой класс модели?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Я понимаю из вопроса, что вам могут понадобиться два случая:

  • Отправить свойство в JSON, у которого нет соответствующего поля в объекте User.В этом случае вам все еще нужно использовать объект User с предоставленными полями и игнорировать остальное, которое было предоставлено в JSON
  • Отправить дополнительные свойства в JSON, и вам все равно нужно захватить их в User объект без , определяющий эти дополнительные свойства конкретно в объекте.

Я думаю, что в обоих случаях лучше использовать Джексона, чем Гсона, поскольку он обладает более богатым управлением маршалингом над объектами.Таким образом, мое решение ниже предполагает, что вы будете использовать Джексона с сетью Spring - maven-зависимость для Джексона выглядит следующим образом:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
</dependency>

Первый случай

В этом случаеДжексон должен игнорировать свойство metaInfoId, когда оно десериализует JSON в объект User.Для этого добавьте эту аннотацию в начало вашего User класса.

@JsonIgnoreProperties(ignoreUnknown = true)
class User {
    private String firstName;
    private String lastName;

    // the rest of the class definition
}

Второй случай

Во втором случае вам все еще нужнозахватить дополнительные свойства.Я бы предложил добавить catch all HashMap, который принимает дополнительные неопределенные свойства, и вы можете получить к нему доступ по ключу / значению.Чтобы достичь этого, вам нужно добавить следующее к вашему User классу, или лучше создать абстрактный класс, который имеет этот код, где User расширяет его.

class User {
    private String firstName;
    private String lastName;
    private Map<String, Object> extra;

    @JsonAnySetter
    public void addExtra(final String key, final Object value){
        this.extra.put(key, value);  
    }

    @JsonAnyGetter
    public Map<String, Object> getExtra() {
        return Collections.unmodifiableMap(this.extra);
    }

    // the rest of the class definition
}

Надеюсь, это поможет

0 голосов
/ 17 декабря 2018

Вы можете аннотировать ваш POJO с помощью @JsonIgnoreProperties(ignoreUnknown = true), поэтому поля, которые он не содержит, игнорируются.Например,

@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
    private int id;
    private String firstName;
    private String lastName;

    ... getters & setters ...
}

Кроме того, вы не должны включать метаданные в текст вашего запроса на отдых.Правильное место для этой информации будет в заголовках.Это изменит сигнатуру вашего метода на:

@PostMapping("/update)
public void update(@RequestBody User user, @RequestHeader(value="metaInfoId") String metaInfoId) {
    ...
}

Если вам необходимо добавить информацию в запрос, вам потребуется обновить класс User pojo, чтобы включить это поле (или он должен расширять класс с помощьюполе metaInfoId)

Наконец, вы действительно не хотите создавать новый тип.Вы можете изменить подпись, чтобы принять карту и получить необходимую информацию, например:

@PostMapping("/update)
public void update(@RequestBody Map<String, Object> userMap) {
    String metaInfoId = userMap.get("metaInfoId");

    ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
    final User user = mapper.convertValue(userMap, User.class);
}
...