0

Context:

Suppose the current way to update a person is to use HTTP PATCH, where you can set the firstname and lastname:

{
  "firstname": "john", 
  "lastname": "doe"
}

And you want to add an extra optional field birthdate to the person. There is no problem for the GET or PUT (as it's optional). But can it be added to the PATCH?

{
  "firstname": "john", 
  "lastname": "doe",
  "birthdate": "01-01-2000"
}

Problem:

New clients can set the field, but old clients wanting to PATCH the name, will delete the birthdate value.

Solutions that I don't want

Not updating fields when the response field is missing. But what if the API needs to allow deleting specific fields (like deleting a birthdate)?

You could argue to only delete the field when it's explicitly mentioned in the request. But my backend is in Java and in any case, it will map to a LocalDate null value.

{
  "firstname": "john", 
  "lastname": "doe",
  "birthdate": null // delete the value as its explicitly mentioned
}

I dont want to version my API for every field that I add.

What are the solutions?

3

A quick review of PATCH method for HTTP

The PATCH method requests that a set of changes described in the request entity be applied to the resource identified by the Request-URI. The set of changes is represented in a format called a "patch document" identified by a media type.

(emphasis added)

You can support any patch document formats you like, including rolling your own, but if you want to describe changes to JSON representations, then RFC 6902 and RFC 7396 have done a bunch of the work for you.

The basic idea is that the client will GET your latest-but-backwards-compatible json representation, make changes only to the fields that it understands, and send back either a copy of its locally revised document, or a patch document that describes the changes that were made.

Note that the client needs to be smart enough to understand that it may need to be forward compatible, applying "must-ignore, must-forward" to fields that it doesn't understand.

David Orchard wrote a decent introduction to forward/backward compatibility concerns in XML; you might also track down Mike Amundsen's Twelve Patterns for Evolvable APIs.

1

You seem to be confusing PATCH and PUT. PATCH is for updating entities, and PUT is for replacing entities. Note the differences in the formal specifications:

PATCH (https://tools.ietf.org/html/rfc5789#section-2):

The PATCH method requests that a set of changes described in the request entity be applied to the resource identified by the Request-URI.

PUT (https://tools.ietf.org/html/rfc7231#section-4.3.4):

The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

To implement PATCH properly, only the fields present in the request should be updated. If an older implementation calls the PATCH endpoint with only firstname and lastname after you've added birthdate, the birthdate for the entity should be unchanged by the request.

If you want to implement PUT instead of (or in addition to) PATCH, it would be a good idea to version the PUT when you make any changes to the exposed fields on the entity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.