简体   繁体   English

春天@RequestBody不使用pojo?

[英]Spring @RequestBody without using a pojo?

I am using Spring Boot and I have a method defined like this in my controller 我正在使用Spring Boot,并且在控制器中定义了这样的方法

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

However in my post request from client(frontend or postman for example), I have something like this: 但是,在我从客户端(例如前端或邮递员)发出的发帖请求中,我有类似以下内容:

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

The thing is my User pojo has only firstName , id and lastName instance fields in it.However in my request I have to send metaInfoId as well for some other needs. 事情是我的用户pojo中只有firstNameidlastName实例字段,但是在我的请求中我have to send metaInfoId来满足其他一些需求。 So how can I retrieve or separate metaInfoId and User model in my controller method above? 那么如何在上面的控制器方法中检索或分离metaInfoIdUser模型?

Do I have to create another model class called UserModelRequest and add all User fields along with metaInfoId field and then use @RequestBody ? 我是否必须创建另一个名为UserModelRequest模型类,并将所有User字段与metaInfoId字段一起添加,然后使用@RequestBody Is there a way to simply remove metaInfoId from the request and then take everything else and dump it into User pojo? 有没有一种方法可以简单地从请求中删除metaInfoId ,然后取出其他所有内容并将其转储到User pojo中? You could do this easily in nodejs for example(just splice your object and take what you need). 例如,您可以在nodejs中轻松地做到这一点(只需拼接对象并获取所需的内容)。

So is there a way to do it in java spring without having to create another model class? 那么有没有一种方法可以在Java Spring中执行而不必创建另一个模型类?

You can annotate your POJO with @JsonIgnoreProperties(ignoreUnknown = true) so the fields that it does not contain are ignored. 您可以使用@JsonIgnoreProperties(ignoreUnknown = true)注释POJO,以便忽略其中不包含的字段。 Ex 防爆

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

    ... getters & setters ...
}

Additionally, you should not include metadata in the body of your rest request. 此外,您不应在其余请求的正文中包含元数据。 The correct place for this information would be in a headers. 此信息的正确位置将在标题中。 This would change your method signature to: 这会将您的方法签名更改为:

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

If you must add the information in the request, then your would need to update the User pojo class to include this field (Or have it extend a class with the metaInfoId field) 如果必须在请求中添加信息,则需要更新User pojo类以包括此字段(或者让它使用metaInfoId字段扩展类)

Lastly, you really don't want to create a new type. 最后,您真的不想创建新类型。 You can change the signature to accept a map and retrieve the necessary info like: 您可以更改签名以接受地图并检索必要的信息,例如:

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

I understand from the question that you may need two cases: 从这个问题中我了解到您可能需要两种情况:

  • Send a property in the JSON that does not have a corresponding field in the User object. 在JSON中发送一个属性,该属性在User对象中没有相应的字段。 In that case, you need to still use the User object with the supplied fields and ignoring the rest that was provided in the JSON 在这种情况下,您仍然需要将User对象与提供的字段一起使用,并忽略JSON中提供的其余部分
  • Send additional properties in the JSON and you still need to capture them in the User object without defining those extra properties specifically in the object. 在JSON中发送其他属性,您仍然需要在User对象中捕获它们, 而无需在对象中专门定义那些额外的属性。

I think in both cases, it is better to use Jackson than Gson as it has richer marshaling controls over the objects. 我认为在这两种情况下,使用Jackson都比Gson更好,因为它对对象具有更丰富的编组控制。 Thus, my below solution assumes that you will use Jackson with Spring web - the maven dependency for Jackson is as follows: 因此,我的以下解决方案假定您将在Spring Web上使用Jackson-杰克逊的maven依赖关系如下:

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

First Case 第一案

In this case, you need Jackson to ignore the metaInfoId property when it deserializes the JSON to the User object. 在这种情况下,当杰克逊将JSON反序列化为User对象时,您需要忽略metaInfoId属性。 To achieve this, please add this annotation to the top of your User class. 为此,请将此批注添加到User类的顶部。

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

    // the rest of the class definition
}

Second Case 第二种情况

In the second case, you still need to capture the extra properties. 在第二种情况下,您仍然需要捕获额外的属性。 I'd suggest adding a catch all HashMap that accepts the extra undefined properties and you can access it by key/value. 我建议添加一个接受所有额外的未定义属性的catch HashMap ,您可以通过键/值对其进行访问。 To achieve this, you'll need to add the following to your User class, or better to create an abstract class that has this code where User extends it. 为此,您需要将以下内容添加到您的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
}

Hope this helps 希望这可以帮助

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

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