REST Array manipulation best practice

2020-04-11 08:25发布

问题:

I have full access to foo resource via REST:

{
  "name": "foo",
  "tags": [
    "tag01",
    "tag02",
    "tag03"
  ]
}

I would like to delete tag01 in tags array.

Usually I would GET \foo and PUT \foo it back without tag01. In this case this object is small, so this is ok.

But let's assume it's much bigger. For this case I don't like to download and upload this data. After some google research I found out http PATCH. I looks like exactly what I need.

My request in PATCH way is now

PATCH /foo/tags?op={add|delete}

To delete I would use:

PATCH /foo/tags?op=delete

With this data:

{
  "value": "tag01"
}

There are now two thinks that I don't like:

  • query field op - are there some deafult names described in rfc or smth. like this
  • member value in request data - this is also freely chosen name

It doesn't look correct to me.

Is there some other way to manipulate arrays via REST?

Are there some name conventions to do it in PATCH way?

回答1:

The payload of a PATCH should contain "instructions describing how a resource currently residing on the origin server should be modified to produce a new version". All information should be passed in the payload and not in query-params.

For instance you could send:

PATCH /foo

[
  { 
    "op": "remove",
    "path": "/tags/0" 
  }
]

Path /tags/0 points to the first element of the array. The remaining elements should be shifted to the left.

See the JSON Patch draft for more details.



回答2:

Is there some other way to manipulate arrays via REST?

Yes, because it is not correct. By REST you map your URLs to resources (not operations) and you manipulate resources using HTTP methods and sending representations. Having an op:remove in an URL or in a representation is wrong.

Are there some name conventions to do it in PATCH way?

No there are no REST naming conventions. The URI structure does not matter by REST clients, because they follow hyperlinks with semantic annotations.

If you need an op:remove or similar somewhere, then it indicates that your URI - resource mapping is not good. Probably you have to define a new resource or rethink the resource structure.

I would describe what you want as a bulk create and bulk delete. You can model this cases with something like:

  • POST /collection [{},{},...] -> 201
  • DELETE /collection?filter="..." -> 204

In order to delete something from a collection you need a resource identifier URI. In this case this can contain the tag name or the index in the array (if it is ordered).

  • /foo/tags/tag01
  • /foo/tags/0

It is up to you, but I would use the tag name.

After that it is pretty simple:

  • POST /foo/tags ["a","b","c"]
  • DELETE /foor/tags?name="a,b,c"

So PATCH is not the method you are looking for, because you are creating and removing resources and not replacing them.