Luciano
Luciano

Reputation: 857

How to POST a JSON payload to a @RequestParam in Spring MVC

I'm using Spring Boot (latest version, 1.3.6) and I want to create a REST endpoint which accepts a bunch of arguments and a JSON object. Something like:

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

In the Spring controller I'm currently doing:

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

  ...
}

The json argument doesn't get serialized into a Person object. I get a

400 error: the parameter json is not present.

Obviously, I can make the json argument as String and parse the payload inside the controller method, but that kind of defies the point of using Spring MVC.

It all works if I use @RequestBody, but then I loose the possibility to POST separate arguments outside the JSON body.

Is there a way in Spring MVC to "mix" normal POST arguments and JSON objects?

Upvotes: 28

Views: 78523

Answers (4)

Rich
Rich

Reputation: 15455

You can do this by registering a Converter from String to your parameter type using an auto-wired ObjectMapper:

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

Upvotes: 16

Sorul
Sorul

Reputation: 354

User:

 @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":"[email protected]","password":"1234"}

You can use @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";
}

Upvotes: -3

egemen
egemen

Reputation: 839

you can use RequestEntity.

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

Upvotes: 0

Mosd
Mosd

Reputation: 1682

Yes,is possible to send both params and body with a post method: Example server side:

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

and on your client:

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"}'

Enjoy

Upvotes: 30

Related Questions