API examples using JSON PATCH for partial updates - rest

I'm looking for the best solution to apply a partial update to an object with a REST API (ASP.NET)
I originally wanted to use "JSON Merge Patch" format (rfc7396), but I was not able to do it with ASP.NET (hard to differentiate ignored fields, and fields set to null)
I tried to use PATCH with JSON PATCH format and it is working.
Ex. :
[
{ "op": "replace", "path": "/Name", "value": "patchedValue" },
{ "op": "replace", "path": "/EnumTest", "value": "blo" },
{ "op": "replace", "path": "/SubItem/Name", "value": "patchedValue" }
]
I see that Microsoft support this format (asp.net core json patch), but I have no idea if this format is often used. I don't want to be the only one using it... I'm looking for API from big companies that is using this format for partial update. Do you have some examples ?

Related

Should the resource ID be put in URL of PUT and PATCH requests?

Should PUT's and PATCH's URL contains ID or could it be put inside the body?
PUT /person/UUID {"name": "Jimmy"}
OR
PUT /person/{"UUID":1, "name": "Jimmy"}
( the same for the PATCH)
?
As PUT is defined as Replace the current document found at the URI location with the one provided in the payload sending a PUT request to /person should probably lead to a removal of any person managed by that particular endpoint, in case that URI represents a collection of persons.
As mentioned in this post one might use a URI without some special entity identifier in case this is an all purpose container. Think of a clipboard where you can copy some data to to later on retrieve it to paste it somewhere else. In such a case the identifier is implicitly given by the URI itself, as after all URI stands for unique resource identifier
Note that a URI as a whole identifies a resource and does not necessarily imply some form of parent-child structure. A client especially should not attempt to extract knowledge from an URI at all.
In regards to PATCH it depends. Usually one should use a media-type that is intended for patching such as JSON Patch or JSON Merge Patch.
The former representation defines certain fields that state that a field should be added, removed or replaced with a given value in a notation like the one listed below:
PATCH /my/data HTTP/1.1
Host: example.org
Content-Length: 326
Content-Type: application/json-patch+json
If-Match: "abc123"
[
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]
JSON Merge Patch however works differently. It defines some default rules that instruct a server on how to apply the changes to the target document. A document like below i.e. will either add or update field a to have value z afterwards while the property f of c's object has to be deleted. All the other remaining properties of that resource remain as they are.
PATCH /target HTTP/1.1
Host: example.org
Content-Type: application/merge-patch+json
{
"a":"z",
"c": {
"f": null
}
}
Both of these media-types could be used to send a request directly to the "collection"-resource as both can target sub-elements by definition. However, in terms of caching I'd try to avoid it.
Caching in HTTP works de facto on the URI of the resource. Any unsafe operation performed on that URI leads to the cache invalidating a stored representation for that target. I.e. if you previously invoked GET /person/1 and now perform a PUT or PATCH, which both are unsafe operations, on /person the data might get updated, though a client requesting GET /person/1 afterwards may still retrieve the cached response via the cache as it is unaware of any changes done to that resource.

Resolving 400 error when creating new work item on DevOps API 4.1

I have created a new custom field in my DevOps work item type and I can see the new field via the API using _apis/wit/fields/Custom.fieldname however when I post a new work item using the API I get a 400 bad request.
I'm using version 4.1 of the DevOps API and my array of operations does contain a mixture of values in quotes and this numeric entry.
Can anyone provide me with an example json array that should be valid please?
A 400 Bad Request usually means that your request body either is missing invalid keys or has invalid syntax.
I built a demo to test if Decimal field type will generate any problems following Create Work Item:
POST https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/${type}?api-version=4.1
Request body:
[{
"op": "add",
"path": "/fields/System.Title",
"from": null,
"value": "Sample123"
},
{
"op": "add",
"path": "/fields/Custom.MyField",
"value": 0.5
}]
This is working well:
This 400 problem should be caused by other part of your Request body.

PATCH in REST and null

We have an article resource with properties:
title
image
description
status: published | draft
if we want only to remove image we make request
{title: null, image: null, description: null, status: null}
if we want only to update status we make request
{title: null, image: null, description: null, status: draft}
but in this case image also will be removed
How in REST to update only one property?
Performing partial modifications to a resource
The PATCH method can be used to perform partial modifications to a resource. The request payload should contain a set of instructions describing how the resource will be modified. See the following quote from the RFC 5789:
2. The PATCH Method
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 difference between the PUT and PATCH requests is reflected in the way the server processes the enclosed entity to modify the resource identified by the Request-URI. In a PUT request, the enclosed entity is considered to be a modified version of the resource stored on the origin server, and the client is requesting that the stored version be replaced. With PATCH, however, the enclosed entity contains a set of instructions describing how a resource currently residing on the origin server should be modified to produce a new version. [...]
To describe such set of instructions, you can use JSON Patch defined in the RFC 6902:
1. Introduction
JSON Patch is a format (identified by the media type application/json-patch+json) for expressing a sequence of operations to apply to a target JSON document; it is suitable for use with the HTTP PATCH method.
This format is also potentially useful in other cases in which it is necessary to make partial updates to a JSON document or to a data structure that has similar constraints [...]
Examples with JSON Patch
To update the status, you can do the following:
PATCH /articles/1 HTTP/1.1
Host: example.com
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/status", "value": "draft" }
]
Use the following to remove the image:
PATCH /articles/1 HTTP/1.1
Host: example.com
Content-Type: application/json-patch+json
[
{ "op": "remove", "path": "/image" }
]
And use the following to update the status and remove the image:
PATCH /articles/1 HTTP/1.1
Host: example.com
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/status", "value": "draft" },
{ "op": "remove", "path": "/image" }
]
Alternatively to JSON Patch, you may want to consider JSON Merge Patch defined in the RFC 7396: it's also a means of describing a set of modifications to a target resource's content.
Let me give an example which troubles me when using JSON-Patch message in PATCH message in a RESTFul API.
If we have a structure like:
{"books": [
{"title": "HTTP-Protocol", "image": "http.jpg", "description": "A standard book on HTTP", "status": "Available"},
{"title": "JSON-Patch", "image": "patching.jpg", "description": "Explanation on how to use json-patch in RESTFul", "status": "Planned"},
{"title": "RESTFul", "image": "fielding.jpg", "description": "Representational state transfer", "status": "Available"}
]}
Now the client who requested this information wants to change the status of the third book (RESTFul) from "Available" to "Borrowed".
Using JSON-Patch he would send the following message:
[
{
"op": "replace",
"path": "/books/2/status",
"value": "Borrowed"
}
]
Meaning that from the list, as he saw it, he wants to change the status of the third item. But since a RESTFul API call is stateless the server does not know anymore what list it gave to the client. Maybe in the mean time a new book was added and the list on the server change to:
{"books": [
{"title": "HTTP-Protocol", "image": "http.jpg", "description": "A standard book on HTTP", "status": "Available"},
{"title": "In between", "image": "destroy.jpg", "description": "Not RESTFul?", "status": "Available"},
{"title": "JSON-Patch", "image": "patching.jpg", "description": "Explanation on how to use json-patch in RESTFul", "status": "Planned"},
{"title": "RESTFul", "image": "fielding.jpg", "description": "Representational state transfer", "status": "Available"}
]}
Then this json-patch message received from the client will change the book with the title "JSON-Patch" and not the book with title "RESTFul" as intended by the client.
What is in your opinion the solution for this problem?

Areapath is not correct in programmatically generated TFS/VSTS workitem

I am trying to create workitem in TFS/VSTS with custom area-path
for example I want to be my workitem areapath to be "cde"
Area-paths in my project are similar to below
My patch element for area-path is as below.
{
"op": "add",
"path": "/fields/System.AreaPath",
"value": "VSTS_TFS_Test\abc\cde"
}
I am using batch create method for this hence REST call url is as below
<<my tfs collection url>>/_apis/wit/$batch?api-version=1.0
However this always just display project file (VSTS_TFS_Test) as area in work item. Please refer below screen.
I wanted to "cde" to be area in work item. Please provide some guidence to make this possible
references :
https://www.visualstudio.com/en-us/docs/integrate/api/wit/work-items
The problem should be your patch element.
Just try below patch element:
{
"op": "add",
"path": "/fields/System.AreaPath",
"value": "VSTS_TFS_Test\\abc\\cde"
}
After the patch, just refresh your browser to check the work item again.

How to delete list of items with REST API

I'm wondering about deletion of bunch items using REST API. But I can't find right way. I'm implementing this just by POST method. And it seems as deviation from REST nature. Is there some way with DELETE method for deletion of a collection?
I see two ways to do that with REST:
If you want to delete all the elements, you can use the method DELETE on a list resource itself. For example: DELETE /contacts/ will remove all contacts.
If you to delete only a subset, you can leverage the PATCH method and the JSON PATCH format (see http://jsonpatch.com/ and https://www.rfc-editor.org/rfc/rfc6902) to specify which elements to delete. Here is a sample:
PATCH /contacts
[
{ "op": "remove", "path": "/contacts/1" },
{ "op": "remove", "path": "/contacts/2" },
{ "op": "remove", "path": "/contacts/3" }
]
The following could give you some hints: https://templth.wordpress.com/2015/05/14/implementing-bulk-updates-within-restful-services/.
Hope it helps you,
Thierry