Search code examples
javaresthttpjax-rshttp-patch

Patch vs merge-patch which is appropriate?


trying to see which models are best suited for api (low updates, but object structure could change often, high read application)

I have a resource like this

  1. Epic (id, name, description, start date, close date, status, stories)
  2. Story (id, name, description, start date, close date, status, tasks)
  3. Task (id, name, description, start date, resolution date, resolution)

If I need to support just update of these ,

  1. update Epic name or description or dates or status
  2. update Story name or description or dates or status
  3. update Task name or description or dates or status

which makes sense?

PATCH with application/merge-patch+json RFC 7396

the resource should match target object structure

  1. epics/{id}
  2. epics/{id1}/stories/{id2} .. and so on

PATCH with application/json - I am inclined to choose this as there is no need so strictly enforce RFC 7396 and flexibility to update the rules of updates.

your custom rules to update (but technically - I could just send the resource attributes that needs updates similar to application/merge-patch+json)

  1. epics/{id}
  2. epics/{id1}/stories/{id2} .. and so on

PUT with application/json

the resource should match all fields and create new object and replace (or cheat and just update only like in patch)

  1. epics/{id}
  2. epics/{id1}/stories/{id2} .. and so on

PUT with application/json

or cheat and just update only like in patch but use put

  1. epics/{id}
  2. epics/{id1}/stories/{id2} .. and so on

Solution

  • From the perspective of REST, the important thing to keep in mind is the uniform interface -- you have some resource with an application/json representation. I can GET your representation, and make local edits to it using whatever my favorite tool might be.

    If I then want to propose that the resource should be changed to match my representation, we choose the appropriate method from the HTTP protocol. In other words, the methods in HTTP are all part of the "transport this document over a network" domain. (Ref: Jim Webber, 2011).

    So realistically, supporting "all of them" is the way to ensure the widest number of generic clients can be used to interact with your resources.

    PUT /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: application/json
    

    Perfectly reasonable starting point; it has a couple of advantages - the semantics are idempotent, so clients know that a lost request can be repeated, and HTTP PUT includes semantics for important use cases like "we accepted your representation as is" that allow you to reduce network pressure.

    PUT may be an unfortunate choice when the representation is much larger than the changes.

    PATCH /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: ????
    

    This is a perfectly reasonable way to deal with small changes to large representations. You give up some of the advantages of PUT - lost messages are now more complicated to deal with.

    PATCH /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: application/json
    

    Not at any odds. application/json is not a patch document format -- you have no way of knowing what changes are being described by such a representation without some sort of out-of-band agreement.

    PATCH /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: application/vnd.example.patch+json
    
    PATCH /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: application/prs.example.patch+json
    

    This is the "REST" way to do the previous bit; you define a custom media type, and document the semantics, and then any client that implements your media type can use it. The vendor tree and vanity tree are available. The +json bit is the structured syntax name suffix, which offers a structure hint for consumers that don't recognize the base subtype.

    PATCH /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: application/json-patch+json
    
    PATCH /31E772D3-0157-4B52-8243-75EEAB946E65
    Content-Type: application/merge-patch+json
    

    Also excellent choices, because these two types have been standardized in RFC 6902 and RFC 7936; you have a much better chance that a client will already know these types.

    A client that knows about HTTP PATCH will presumably also know how to use the OPTIONS method to discover what methods and patch document formats the server is prepared to handle.

    OPTIONS /31E772D3-0157-4B52-8243-75EEAB946E65
    
    HTTP/1.1 204 No Content
    Allow: OPTIONS, GET, HEAD, PUT, PATCH
    Accept-Patch: application/prs.example.patch+json, application/json-patch+json, application/merge-patch+json