繁体   English   中英

春天@RequestBody不使用pojo?

[英]Spring @RequestBody without using a pojo?

我正在使用Spring Boot,并且在控制器中定义了这样的方法

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

但是,在我从客户端(例如前端或邮递员)发出的发帖请求中,我有类似以下内容:

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

事情是我的用户pojo中只有firstNameidlastName实例字段,但是在我的请求中我have to send metaInfoId来满足其他一些需求。 那么如何在上面的控制器方法中检索或分离metaInfoIdUser模型?

我是否必须创建另一个名为UserModelRequest模型类,并将所有User字段与metaInfoId字段一起添加,然后使用@RequestBody 有没有一种方法可以简单地从请求中删除metaInfoId ,然后取出其他所有内容并将其转储到User pojo中? 例如,您可以在nodejs中轻松地做到这一点(只需拼接对象并获取所需的内容)。

那么有没有一种方法可以在Java Spring中执行而不必创建另一个模型类?

您可以使用@JsonIgnoreProperties(ignoreUnknown = true)注释POJO,以便忽略其中不包含的字段。 防爆

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

从这个问题中我了解到您可能需要两种情况:

  • 在JSON中发送一个属性,该属性在User对象中没有相应的字段。 在这种情况下,您仍然需要将User对象与提供的字段一起使用,并忽略JSON中提供的其余部分
  • 在JSON中发送其他属性,您仍然需要在User对象中捕获它们, 而无需在对象中专门定义那些额外的属性。

我认为在这两种情况下,使用Jackson都比Gson更好,因为它对对象具有更丰富的编组控制。 因此,我的以下解决方案假定您将在Spring Web上使用Jackson-杰克逊的maven依赖关系如下:

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

第一案

在这种情况下,当杰克逊将JSON反序列化为User对象时,您需要忽略metaInfoId属性。 为此,请将此批注添加到User类的顶部。

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

    // the rest of the class definition
}

第二种情况

在第二种情况下,您仍然需要捕获额外的属性。 我建议添加一个接受所有额外的未定义属性的catch 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
}

希望这可以帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM