How should I expose pagination for a REST API by using HAL format, should I just wrap everything in another HAL formatted object with pagination metadata or ?
Is there a suggested pagination format under REST API HAL format ?
UPDATE
Example without the pagination
[
{
"Id": "SomeId",
"Attribute": 5,
"_links": {
"User": { "href": "http://mywebapi/etc", "templated": true }
},
"_embedded": { "User": { "Id": "SomeId","_links": {},"_embedded": {}} }
},
{
"Id": "SomeId",
"Attribute": 5,
"_links": {
"User": { "href": "http://mywebapi/etc", "templated": true }
},
"_embedded": { "User": { "Id": "SomeId","_links": {},"_embedded": {}} }
}
]
Example with the pagination
{
"_embedded": {
"items":
[
{
"Id": "SomeId",
"Attribute": 5,
"_links": {
"User": { "href": "http://mywebapi/etc", "templated": true }
},
"_embedded": { "User": { "Id": "SomeId","_links": {},"_embedded": {}} }
},
{
"Id": "SomeId",
"Attribute": 5,
"_links": {
"User": { "href": "http://mywebapi/etc", "templated": true }
},
"_embedded": { "User": { "Id": "SomeId","_links": {},"_embedded": {}} }
}
]},
"_links": {
"next": "next link",
"previous": "next link"
},
"_totalCount": "100"
}
It this a good practice or not ?
By the way you have an example in proper HAL RFC
https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-06#section-6
"_links": {
"self": { "href": "/orders" },
"next": { "href": "/orders?page=2" },
"find": { "href": "/orders{?id}", "templated": true }
}
What i am not sure is about "_totalCount" ... i am also figuring out what would be the best way to incude a totalCount attribute in HAL format
Use links with rel="next" and rel="previous"
_totalcount can be problematic. Is it inherent property of the resource you return? Most likely not.
If you do have it, then you will be forced to provide this value every time for every page of the resource. If the total collection is very large, it will become necessary to store the count somewhere to satisfy the API. In many cases, the count may be harder to get. For example, if you implement based on other services that provide continuation token, getting _totalcount populated will become hard. If you have SQL table, it might be fairly easy to get but it comes at a cost too.
Is it really valuable for the client or UI? I would avoid if possible.
Related
I know I am close on this, the error messages are getting nicer. Currently, I can call a similar call to update the seller's email no issue via Postman currently, working on updating the amount and associated objects. Something in my request format is off.
Is my breakdown section in the correct location? The amount_breakdown documentation looks like it is on same level as value and currency_code, so does it need to move into that section.
Here's my request JSON via Postman:
[
{
"op": "replace",
"path": "/purchase_units/#reference_id=='default'/amount",
"value": {
"currency_code": "CAD",
"value": "2",
"amount": {
"currency_code": "CAD",
"value": "2",
"breakdown": {
"item_total": {
"currency_code": "CAD",
"value": "2"
},
"tax_total": {
"value": "0",
"currency_code": "CAD"
}
}
},
"items": [
{
"name": "First Product Name",
"description": "Optional descriptive text..",
"unit_amount": {
"currency_code": "CAD",
"value": "2"
},
"tax": {
"value": "0",
"currency_code": "CAD"
},
"quantity": "1"
}
]
}
}
]
RESPONSE:
{
"name": "UNPROCESSABLE_ENTITY",
"details": [
{
"field": "/purchase_units/#reference_id=='default'/amount/breakdown/item_total",
"location": "body",
"issue": "ITEM_TOTAL_REQUIRED",
"description": "If item details are specified (items.unit_amount and items.quantity) corresponding amount.breakdown.item_total is required."
}
],
"message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
"debug_id": "acecd3643c994",
"links": [
{
"href": "https://developer.paypal.com/docs/api/orders/v2/#error-ITEM_TOTAL_REQUIRED",
"rel": "information_link",
"method": "GET"
}
]
}
Thanks for any help!
Different variations of objects.
I can get the other PATCH operation working no issue but it is much simpler in object structure
There should be no amount key under the /amount path, and the items array does not belong at that /amount path either.
We thought of a system like which is get meta data and data from backend, and use with these datas UI will render.
Some advantages for us:
Business-independent UI components.
Easy adaptation to channel-based business growth.
Example:
[
{
"popup": {
"title": "All Orders",
"row": [
{
"title": "An Order",
"image": {
"position": "LEFT",
"source": "my.jpg"
}
}
]
}
},
{
"orderDetail": {
"orderNumber": "test",
"orderDate": "test",
"platform": null,
"paymentType": "test"
}
}
]
Have you any suggestion for this, is that a good idea, what are the advantages and disadvantages according to you ?
Are there any tools you can recommend for this function?
Assuming I have an endpoint GET /api/foos/{id} which has optional parameters: includes, query, type should I create a link for each of the 'usecases' or can I include it as a single link?
Should it look more like this:
"_links":{
"self": { "href": "/api/foos/1" },
"includes": { "href": "/api/foos/1{?includes}", "templated": true },
"query": { "href": "/api/foos/1{?query}", "templated": true },
"type": { "href": "/api/foos/1{?type}", "templated": true },
}
Or maybe like this:
"_links":{
"self": { "href": "/api/foos/1" },
"query": { "href": "/api/foos/1{?includes}{?query}{?type}", "templated": true },
}
What if I also have paging related links, like next, prev etc. Should I include these templates for them, too? For example:
"next": { "href": "/api/foos?page=2{?includes}", "templated": true }
According to RFC6570, Section 3.2.1 (which is the foundation for URL templating) you can add multiple parameters and parameter without a value will be ignored:
A variable that is undefined (Section 2.3) has no value and is ignored by the expansion process.
That means for your example that you can use following HAL response:
"_links":{
"self": { "href": "/api/foos/1" },
"query": { "href": "/api/foos/1{?includes,query,type}", "templated": true },
}
And it should work for your paging example as well.
I've written a JQ search that outputs the following, but I cannot work out how to get into the detail and extract specific information from this.
{
"https://www.example.org/rest/relation/node/recording/revision_uid": [
{
"_links": {
"self": {
"href": "https://www.example.org/user/37?_format=hal_json"
},
"type": {
"href": "https://www.example.org/rest/type/user/user"
}
},
"uuid": [
{
"value": "d40684cf-2321-42d2-9194"
}
]
}
],
"https://www.example.org/rest/relation/node/recording/uid": [
{
"_links": {
"self": {
"href": "https://www.example.org/user/37?_format=hal_json"
},
"type": {
"href": "https://www.example.org/rest/type/user/user"
}
},
"uuid": [
{
"value": "d40684cf-2321-42d2-9194"
}
],
"lang": "en"
}
],
"https://www.example.org/rest/relation/node/recording/field_category": [
{
"_links": {
"self": {
"href": "https://www.example.org/simplecategory?_format=hal_json"
},
"type": {
"href": "https://www.example.org/rest/type/taxonomy_term/tags"
}
},
"uuid": [
{
"value": "3fef93d5-926a-41aa-95cb"
}
]
}
],
"https://www.example.org/rest/relation/node/recording/field_part1_speaker": [
{
"_links": {
"self": {
"href": "https://www.example.org/by/speakername?_format=hal_json"
},
"type": {
"href": "https://www.example.org/rest/type/taxonomy_term/author"
}
},
"uuid": [
{
"value": "fb6c806f-fa6a-4aa0-89ef"
}
]
}
]
}
How do I write a query that returns 'https://www.example.org/simplecategory?_format=hal_json'?
And I'd then want a similar query that returns 'https://www.example.org/by/speakername?_format=hal_json'
So jq '._embedded' gets me the data above.
I've then tried various combinations to get to the value of https://www.example.org/rest/relation/node/recording/field_category.
- jq '._embedded.https://www.example.org/rest/relation/node/recording/field_category - but of course the URL has special characters in it.
jq .["https://www.example.org/rest/relation/node/recording/field_category"]
jq ."https://www.example.org/rest/relation/node/recording/field_category$"
I've also messed around with some of JQs built in functions, like flatten and to_entries, from_entries. I've also tried regular expressions but my efforts return Cannot iterate over null (null).
How do I write a query that returns 'https://www.example.org/simplecategory?_format=hal_json'?
If you want to specify the top-level key explicitly, the follow-on query would be:
.["https://www.example.org/rest/relation/node/recording/revision_uid"][]
| ._links.self.href
That is, the entire query would be:
._embedded
| .["https://www.example.org/rest/relation/node/recording/revision_uid"][]
| ._links.self.href
And I'd then want a similar query
An alternative to specifying the top-level key explicitly might be to select the href of interest from the array of all of them:
._embedded
| [.[][]._links.self.href]
This would yield:
[
"https://www.example.org/user/37?_format=hal_json",
"https://www.example.org/user/37?_format=hal_json",
"https://www.example.org/simplecategory?_format=hal_json",
"https://www.example.org/by/speakername?_format=hal_json"
]
I am currently specifying an API for my company, in accordance with JSON API specifications.
When retrieving a members ressource with a GET host.com/members/{members_id}, I need to expose many phone numbers phones.
Example:
{
"data": {
"type":"members",
"id": "1",
"attribute": {
"phones": [{
"phone": "",
"type": ""
}]
}
},
"relationships": {
"subscriptions": {
"links": {
"related": "host.com/members/id/subscriptions"
}
},
"relations": {
"links:" {
"related": "host.com/members/id/relations"
}
}
},
"links": {
"self": "host.com/members/id"
}
}
I do not know whether it is relevant to expose a simple list of dictionaries, or if it would be better to create separate ressources accessible at /members/me/phones/{phones_id} with a new relationships for the members linked to phones.
To retrieve a members in one request, I could then do a GET /members/{members_id}?include=phones.
From my developer point of view, it would be easier to access separate ressources rather than managing and posting lists, especially for phones (e.g. delete only one phone), but I would be very happy to have your (too often relevant) external advices.
Thanks for your support !
Can you modify your JSON response? because it is not ideal.
this ideal:
GET host.com/members/{members_id}
returns:
{
"id": "1",
"phones": [{
"phone": "",
"type": ""
}
]
}
GET host.com/members/{members_id}/phones
[
{
"phone": "",
"type": ""
},
{
"phone": "",
"type": ""
}
]