Reputation: 107202
I have a RESTful API that supports two objects so as object A
contains an ordered list of nested objects B
:
Create object A - POST /a
Create object B and add to A - POST /a/<id>/b
Update object B in A - PATCH /a/<id>/b/<id>
What would be a RESTful way to update the order of B
objects in a specific A
?
Option 1: PATCH /a/<id>
with json content that replaces A.Bs
A
has a list of embedded B
s, namely A.Bs
so you can replace that list in its entirety also changing the order on the way. This relies on the client to resubmit the entire list correctly.
Option 2: PATCH /a/<id>
with json content that replaces A.B_order
Add a separate list of B
ids and have the client update it. This is similar to Option 1 but does not rely on the client resubmitting all the objects. It does require the server to manage the list, updating it upon B
creation, and validating the update contains all the required B
ids on list order update.
Option 3: PATCH /a/<id>/b
with json content that replaces A.Bs
The same as Option 1, but with a different URL
Which would be most RESTful and clear?
Any other options?
Upvotes: 3
Views: 1130
Reputation: 99717
The question I would ask myself is: "What does 'order' mean in this case".
The specific instances of B
don't have an order between them. They're all independent resources that are not really 'aware' of each order.
Given that, it's not really the B
resource that you are changing. What are you changing?
Presumably there is a collection of B
's somewhere. You do a GET
request on that collection to get an ordered list of B
's. Do you get that list on /a/<id>
or on /a/<id>/b
?.
Wherever that ordered list is, I would also do the operation to change the order because the order is a 'property' of the collection.
So for the sake of the argument, lets assume that your 'collection of B
lives on /a/<id>b
. What format should that be?
Well, a good REST service will replace the entire state. So as a default I would do a PUT
request on that resource and do a full replace of the entire thing.
If you don't like that idea and want to use PATCH
to update only a part of the collection (and nothing else), I think I would opt for one of these:
json-patch
.Option 2 will likely be a lot simpler to implement, and I would also keep the format as simple as possible.
If you use a format like HAL, a collection is probably a list of links. In that case I would use a syntax like:
{
"_links": {
"item": [
{ "href": "/a/<id>/b/ordered-item-1" },
{ "href": "/a/<id>/b/ordered-item-2" }
]
}
}
If you don't have a hypermedia-style API, you probably use id's and force the client to expand id's in urls. In that case, I'd imagine the format could look like:
{
"items": [ 1, 3, 5, 2]
}
In each case, it's a Good Idea to define your own media type for this, because this format for PATCH has special meaning to your api. For example:
application/vnd.jonathan.patch+json
Upvotes: 0
Reputation: 1597
Given Foo has Bars and Bars are resources (have ID or link), when you need to reorder foo.bars then I would suggest:
’PUT /foos/:id/bars’ with array of IDs or links in the body.
But if Bars are not resources (have no ID), then:
’PATCH /foos/:id’ with body of Foo including complete new array of Foo.bars in the ’bars’ property.
Upvotes: 0
Reputation: 13682
I would suggest using the proposed standard defined in RFC 6902. Specifically, the "move" op would seem to be what you're looking for.
Upvotes: 2