Spring @RequestBody 不使用 pojo?
Spring @RequestBody without using a pojo?
我正在使用 Spring Boot 并且我在我的控制器中定义了一个这样的方法
@PostMapping("/update)
public void update(@RequestBody User user) {
...
}
但是在我的 post 客户端(例如前端或 postman 请求)中,我有这样的东西:
{
"firstName" : "John",
"lastName" : "Doe",
"id" : 1234,
"metaInfoId" : "5457sdg26sg4636"
}
问题是我的用户 pojo 在我的请求 it.However 中只有 firstName
、id
和 lastName
实例字段我 have to send
metaInfoId
以及其他一些需求。那么如何在上面的控制器方法中检索或分离 metaInfoId
和 User
模型呢?
我是否必须创建另一个名为 UserModelRequest
的模型 class 并将所有 User
字段与 metaInfoId
字段一起添加,然后使用 @RequestBody
?有没有一种方法可以简单地从请求中删除 metaInfoId
,然后将其他所有内容转储到 User
pojo 中?例如,你可以在 nodejs 中轻松地做到这一点(只需拼接你的对象并获取你需要的东西)。
那么有没有办法在 java spring 中做到这一点而无需创建另一个模型 class?
您可以使用 @JsonIgnoreProperties(ignoreUnknown = true)
注释您的 POJO,这样它不包含的字段将被忽略。例如
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private int id;
private String firstName;
private String lastName;
... getters & setters ...
}
此外,您不应在休息请求的 body 中包含元数据。此信息的正确位置应在 headers 中。这会将您的方法签名更改为:
@PostMapping("/update)
public void update(@RequestBody User user, @RequestHeader(value="metaInfoId") String metaInfoId) {
...
}
如果您必须在请求中添加信息,那么您需要更新用户 pojo class 以包含此字段(或者让它扩展 class 和 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);
}
从问题中了解到您可能需要两种情况:
- 在JSON中发送一个在
User
对象中没有相应字段的属性。在这种情况下,您仍然需要将 User
对象与提供的字段一起使用,并忽略 JSON 中提供的其余部分
- 在 JSON 中发送额外的属性,您仍然需要在
User
对象中捕获它们 而无需 在对象中专门定义那些额外的属性。
我认为在这两种情况下,使用 Jackson 比使用 Gson 更好,因为它对对象具有更丰富的编组控制。因此,我的以下解决方案假设您将 Jackson 与 Spring web 一起使用 - Jackson 的 Maven 依赖项如下:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
第一个案例
在这种情况下,您需要 Jackson 在将 JSON 反序列化为 User
对象时忽略 metaInfoId
属性。为此,请将此注释添加到 User
class.
的顶部
@JsonIgnoreProperties(ignoreUnknown = true)
class User {
private String firstName;
private String lastName;
// the rest of the class definition
}
第二种情况
在第二种情况下,您仍然需要捕获额外的属性。我建议添加一个 catch all HashMap
来接受额外的未定义属性,您可以通过 key/value 访问它。为此,您需要将以下内容添加到您的 User
class,或者更好地创建一个摘要 class,其中包含此代码 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
}
希望对您有所帮助
我正在使用 Spring Boot 并且我在我的控制器中定义了一个这样的方法
@PostMapping("/update)
public void update(@RequestBody User user) {
...
}
但是在我的 post 客户端(例如前端或 postman 请求)中,我有这样的东西:
{
"firstName" : "John",
"lastName" : "Doe",
"id" : 1234,
"metaInfoId" : "5457sdg26sg4636"
}
问题是我的用户 pojo 在我的请求 it.However 中只有 firstName
、id
和 lastName
实例字段我 have to send
metaInfoId
以及其他一些需求。那么如何在上面的控制器方法中检索或分离 metaInfoId
和 User
模型呢?
我是否必须创建另一个名为 UserModelRequest
的模型 class 并将所有 User
字段与 metaInfoId
字段一起添加,然后使用 @RequestBody
?有没有一种方法可以简单地从请求中删除 metaInfoId
,然后将其他所有内容转储到 User
pojo 中?例如,你可以在 nodejs 中轻松地做到这一点(只需拼接你的对象并获取你需要的东西)。
那么有没有办法在 java spring 中做到这一点而无需创建另一个模型 class?
您可以使用 @JsonIgnoreProperties(ignoreUnknown = true)
注释您的 POJO,这样它不包含的字段将被忽略。例如
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private int id;
private String firstName;
private String lastName;
... getters & setters ...
}
此外,您不应在休息请求的 body 中包含元数据。此信息的正确位置应在 headers 中。这会将您的方法签名更改为:
@PostMapping("/update)
public void update(@RequestBody User user, @RequestHeader(value="metaInfoId") String metaInfoId) {
...
}
如果您必须在请求中添加信息,那么您需要更新用户 pojo class 以包含此字段(或者让它扩展 class 和 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);
}
从问题中了解到您可能需要两种情况:
- 在JSON中发送一个在
User
对象中没有相应字段的属性。在这种情况下,您仍然需要将User
对象与提供的字段一起使用,并忽略 JSON 中提供的其余部分
- 在 JSON 中发送额外的属性,您仍然需要在
User
对象中捕获它们 而无需 在对象中专门定义那些额外的属性。
我认为在这两种情况下,使用 Jackson 比使用 Gson 更好,因为它对对象具有更丰富的编组控制。因此,我的以下解决方案假设您将 Jackson 与 Spring web 一起使用 - Jackson 的 Maven 依赖项如下:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
第一个案例
在这种情况下,您需要 Jackson 在将 JSON 反序列化为 User
对象时忽略 metaInfoId
属性。为此,请将此注释添加到 User
class.
@JsonIgnoreProperties(ignoreUnknown = true)
class User {
private String firstName;
private String lastName;
// the rest of the class definition
}
第二种情况
在第二种情况下,您仍然需要捕获额外的属性。我建议添加一个 catch all HashMap
来接受额外的未定义属性,您可以通过 key/value 访问它。为此,您需要将以下内容添加到您的 User
class,或者更好地创建一个摘要 class,其中包含此代码 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
}
希望对您有所帮助