Java post request with nested objects

I have an object Order which contains another object Person among other properties.

I’m wondering what is the best solution to create an order through a post request.


The first approach in my mind is something like this:

@PostMapping("orders/create")
public void createOrder(@RequestBody Order order) {
    orderRepository.save(order);
}

but what I don’t like about this solution is that the client has to send a json string with all the information about the order and the person at the same time, like this:

{
    "date": 2023-01-01,
    "price": 10,
    "person": {
        "id": 1,
        "name": "Foo",
        ...
    }
}

How can I also make sure that the person passed in the request is actually a person that exists in my database?


The second approach that I can think of is like this:

@PostMapping("orders/create/{personId}")
public void createOrder(@PathVariable Long personId, @RequestBody Order order) {
    Person person = personRepository.findById(personId).orElseThrow();
    order.setPerson(person);
    orderRepository.save(order);
}

but this solution would require a post request like localhost:8080/orders/1 where 1 is the id of the person, which is horrible because it’s too confusing.

I can’t get my head around this, any insights are highly appreciated.

>Solution :

You’re right, it doesn’t make sense to send the personId to the order API. Since you’re passing the personId in the RequestBody, just drop the PathVariable and use what’s in the order.

@PostMapping("orders/create")
public void createOrder(@RequestBody Order order) {
   Person person = personRepository.findById(order.getPerson().getId()).orElseThrow();
   order.setPerson(person);
   orderRepository.save(order);
}

Or, as the comment by E-Riz is eluding to, if the Person is the authenticated user, get them out of the SecurityContext and look them up by their username. Then there would be no need to send the Person in the Order.

Leave a Reply