如何在Spring MVC中将JSON负载POST到@RequestParam?

28

我正在使用Spring Boot(最新版本1.3.6),我想创建一个接受一堆参数和JSON对象的REST端点。例如:

curl -X POST http://localhost:8080/endpoint \
-d arg1=hello \
-d arg2=world \
-d json='{"name":"john", "lastNane":"doe"}'

我目前在Spring控制器中执行以下操作:

public SomeResponseObject endpoint(
@RequestParam(value="arg1", required=true) String arg1, 
@RequestParam(value="arg2", required=true) String arg2,
@RequestParam(value="json", required=true) Person person) {

  ...
}
json参数不会被序列化成Person对象。我得到了一个

400 error: the parameter json is not present.

很显然,我可以将json参数作为字符串传入并在控制器方法中解析有效负载,但这有点违背了使用Spring MVC的初衷。

如果我使用@RequestBody,一切都可以正常工作,但我就失去了在JSON主体之外POST分离参数的可能性。

在Spring MVC中是否有一种方式可以“混合”正常的POST参数和JSON对象?


2
我认为没有办法,而且混合使用表单编码数据和JSON数据也不是一个好主意。决定您想要接受哪一个。 - JB Nizet
2
许多API(如Stripe、Plaid、Stormpath)使用这种方法来逻辑上分离请求数据(例如,如果我正在进行搜索,我可以将搜索条件放在Json表示中,并将分页数据保留在表单的编码位中)。但我理解你的观点。 - Luciano
4个回答

30

是的,可以使用POST方法同时发送参数和请求体:

服务器端示例:

@RequestMapping(value ="test", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public Person updatePerson(@RequestParam("arg1") String arg1,
        @RequestParam("arg2") String arg2,
        @RequestBody Person input) throws IOException {
    System.out.println(arg1);
    System.out.println(arg2);
    input.setName("NewName");
    return input;
}

并且在您的客户端上:

curl -H "Content-Type:application/json; charset=utf-8"
     -X POST
     'http://localhost:8080/smartface/api/email/test?arg1=ffdfa&arg2=test2'
     -d '{"name":"me","lastName":"me last"}'

享受


12
这并没有回答问题,但展示了如何使用绕过方法,而这正是原帖中特别声明不想使用的。 - Rich

15
你可以通过使用自动装配的ObjectMapper注册一个从String类型到你的参数类型的Converter来实现此操作:
import org.springframework.core.convert.converter.Converter;

@Component
public class PersonConverter implements Converter<String, Person> {

    private final ObjectMapper objectMapper;

    public PersonConverter (ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Person convert(String source) {
        try {
            return objectMapper.readValue(source, Person.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

对于使用@RequestParam注释的方法参数,它也能完美运行。 - ddotsdot

0

你可以使用RequestEntity。

public Person getPerson(RequestEntity<Person> requestEntity) {
    return requestEntity.getBody();
}

-3

用户:

 @Entity
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer userId;
    private String name;
    private String password;
    private String email;


    //getter, setter ...
}

JSON:

{"name":"Sam","email":"sam@gmail.com","password":"1234"}

您可以使用@RequestBody

@PostMapping(path="/add")
public String addNewUser (@RequestBody User user) {
    User u = new User(user.getName(),user.getPassword(),user.getEmail());
    userRepository.save(u);
    return "User saved";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接