Reputation: 983
I'm using ZF2 with "zfcampus/zf-rest":"1.2.0"
to return API results.
For a resource named Tag
I receive the response below:
{
"_links": {
"self": {
"href": "http://mydomain/article/tags"
}
},
"_embedded": {
"tags": [
{
"id": 1,
"tag": "news",
"isOfficial": true,
"_links": {
"self": {
"href": "http://mydomain/article/tags"
}
}
}
]
},
"total_items": 1
}
However, I would like to get rid of _links
property under tags resource so I may have a cleaner output.
What I would like to achieve would look like this;
{
"_links": {
"self": {
"href": "http://mydomain/article/tags"
}
},
"_embedded": {
"tags": [
{
"id": 1,
"tag": "news",
"isOfficial": true
}
]
},
"total_items": 1
}
How can I achieve this behavior?
Please mind that router for the endpoint is implemented as:
'api.rest.article.tags' => [
'type' => 'Segment',
'options' => [
'route' => '/article/tags',
'defaults' => [
'controller' => 'Api\V1\ArticleTag\Controller',
],
],
],
Upvotes: 1
Views: 634
Reputation: 44383
When using ZF Hal you will get such a rendered result because self links are an essential part of the Hal-Json standard and your Tag
is considered a Hal Resource and will be rendered as in your example above. You probably registered meta-data and a hydrator for this class and those are used for extracting the entity like that.
If you don't want to render the Tag
as a Hal resource your solution could be as simple as removing the meta-data and hydrator for the class and simply implementing a JsonSerializable
interface into your class and adding a jsonSerialize method that returns the desired result. The renderer will call jsonSerialize
while rendering it instead...
When there is no Hydrator found and an object implements this JsonSerializable interface this is the fallback for extracting your object.
You can see that here in the extractEntity method:
if ($hydrator) {
return $hydrator->extract($entity);
}
if ($entity instanceof JsonSerializable) {
return $entity->jsonSerialize();
}
Check this blog post on JsonSerializable: https://www.sitepoint.com/use-jsonserializable-interface/
Hope this will work for you, if not feel free to comment and I can see if I can suggest an alternative solution.
Upvotes: 1
Reputation: 3468
UPDATE Comment from OP made this answer superfluous. Leaving it as it might help someone. If you're using full Apigility then this is for you.
For one, V1.2.* versions were released in July 2016, as such I would suggest you start with updating your application.
Also, why would you try to "clean" this up, as it were? Removing direct links for retrieval of single objects serves no purpose when getting a collection.
You're doing a "GET /tags" call (Collection) but you want to get a single object.
To get a single item, do a "GET /tags/:id" call, e.g. "GET /tags/1".
The response of a single item should be like this (might differ, using up-to-date Apigility for this):
(Note, local dev env, that's why "http")
Single call: "GET http://api.loc/coordinates/1"
{
"latitude": "33.6062068",
"longitude": "58.7053709",
"id": 1,
"_links": {
"self": {
"href": "http://api.loc/coordinates/1"
}
}
}
Collection call: "GET http://api.loc/coordinates"
{
"_links": {
"self": {
"href": "http://api.loc/coordinates?page=1"
},
"first": {
"href": "http://api.loc/coordinates"
},
"last": {
"href": "http://api.loc/coordinates?page=10"
},
"next": {
"href": "http://api.loc/coordinates?page=2"
}
},
"_embedded": {
"coordinates": [
{
"latitude": "33.6062068",
"longitude": "58.7053709",
"id": 1,
"_links": {
"self": {
"href": "http://api.loc/coordinates/1"
}
}
},
{
"latitude": "60.1948871",
"longitude": "19.2423547",
"id": 2,
"_links": {
"self": {
"href": "http://api.loc/coordinates/2"
}
}
},
{ ... } another 247 results
]
},
"page_count": 10,
"page_size": 25,
"total_items": 249,
"page": 1
}
Links should be generated using the LinkExtractor
class, for which you can employ strategies via configuration. If you're using Apigility (which uses the zfcampus/zf-rest
module you mentioned), you can apply strategies like so:
[ ... ] // more config
'doctrine-hydrator' => [
'Company\\V1\\Rest\\Company\\CompanyHydrator' => [
'entity_class' => \Path\To\Company::class,
'object_manager' => 'doctrine.entitymanager.orm_default',
'by_value' => true,
'strategies' => [
'country' => \ZF\Doctrine\Hydrator\Strategy\EntityExtract::class,
'currency' => \ZF\Doctrine\Hydrator\Strategy\EntityLink::class,
'currencies' => \ZF\Doctrine\Hydrator\Strategy\CollectionExtract::class,
],
[ ... ] // more config
They're provided by Tom Anderson's ZF Doctrine Hydrator package.
The *Link
strategies provide links to objects, links which may be used in GET calls for instance.
The *Extract
strategies straight ensure that an Entity is hydrated into the result and returned instead of a link.
As specifically for removing that _links
bit. If you're using zf-rest
because you're using Apigility, and thus the links are caused by the config for zf-hal
, then you can use the 'force_self_link' => false
option in the 'zf-hal' => []
config. This must be done per set.
See this Apigility docs page and search for "force_self_link".
force_self_link - boolean; set whether a self-referencing link should be automatically generated for the entity. Defaults to true (since its recommended).
I would agree with the docs: recommended to keep this enabled.
UPDATE Comment from OP made this answer superfluous. Leaving it as it might help someone.
Upvotes: 1