hi community i wondered why i don`t have answer to the question is there are something wrong with my question , hope some one give me an answer , just asking to change way or formatting of the question , (improve my questions)
Question About JSON:API Payload Complexity
Hi, I’m currently taking a course on Laracasts with Jeremy, where he builds an API using the token-based authentication approach. In the course, he structures the response payload following the JSON:API specification. However, I find this format quite complex—especially when creating, updating, or patching resources. Is there a recommended or simpler approach for structuring API payloads that I can follow instead? TicketsResourse class
<?php
namespace App\Http\Resources\V1;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @property int $id
* @property string $title
* @property string $description
* @property string $status
* @property int $user_id
* @property User $author
*/
class TicketsResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'type' => 'Ticket',
'id' => $this->id,
'attributes' => [
'title' => $this->title,
$this->mergeWhen(
$request->routeIs('tickets.*'),
[
'description' => $this->description
]
),
'status' => $this->status
],
'links' => [
'self' => route('tickets.show', $this->id)
],
$this->mergeWhen(
$request->routeIs('tickets.*')||
$request->routeIs('authors.tickets.*'),
[
'relationships' => $this->whenLoaded('author', function(){
return [
'author' => [
'data' => [
'type' => 'Author',
'id' => $this->author->id
],
'links' => [
'self' => route('authors.show', $this->author->id)
]
]
];
},[]),
'included' => [
'author' => UsersResource::make($this->whenLoaded('author'))
]
])
];
}
}
Consistency in whether you're returning a collection of users, or a collection of books, the structure is as similar as possible, the same as single entitity responses.
The message here is quite common, and can contain various things (we use it at current $dayJob for returning messages to the FE to display so the languages are handled in the backend).. but it's not mandatory in any shape or form.
Get all users response
{
"message": "Users list",
"data": [
{
"uuid": "e327e77c-443d-43e5-9d92-08bff6348885",
"username": "MyUsername",
"first_name": "Joe",
"last_name": "Bloggs",
"email": "[email protected]"
},
{
"uuid": "87a518f2-2538-4162-8b94-2733e4c8ddca",
"username": "ANotherUsername",
"first_name": "Sally",
"last_name": "Smith",
"email": "[email protected]"
}
],
"pagination": {
"previous": "/users?page=1",
"next": "/users?page=3",
"page": 2,
"total": 6
}
}
Single user response
{
"message": "Single user",
"uuid": "e327e77c-443d-43e5-9d92-08bff6348885",
"username": "MyUsername",
"first_name": "Joe",
"last_name": "Bloggs",
"email": "[email protected]"
}
All books response
{
"message": "Books list",
"data": [
{
"uuid": "7dc3ca73-7766-4ca4-a076-2bd5fb375b6d",
"title": "Best Book Ever! 2025",
"author": "John Jones",
"cover_image": "/book/7dc3ca73-7766-4ca4-a076-2bd5fb375b6d/cover.jpg"
},
{
"uuid": "d2ec3943-3a38-46a7-ab19-701fe5e72989",
"title": "Vintage Book",
"author": "Michelle Evans",
"cover_image": "/book/d2ec3943-3a38-46a7-ab19-701fe5e72989/cover.jpg"
}
],
"pagination": {
"previous": null,
"next": "/users?page=2",
"page": 1,
"total": 50
}
}
Single book response
{
"message": "Single book",
"uuid": "7dc3ca73-7766-4ca4-a076-2bd5fb375b6d",
"title": "Best Book Ever! 2025",
"author": "John Jones",
"cover_image": "/book/7dc3ca73-7766-4ca4-a076-2bd5fb375b6d/cover.jpg"
}
The idea here is that a list of users or a list of books, despite having different properties for the models, the response is consistent:
- Both contain a
messagefield with similar content - Both contain a
dataelement wrapping around multiple entities - Both contain a
paginationobject
The same is said for the single entities:
- Both contain the message field with similar content
- Both contain a single object not wrapped in a
dataproperty - Neither contain pagination (obviously not needed for single entities)
Although the property names are different between the entity types, the response expectations are consistent with each other. This makes using the API much simpler from any client (be it a web front end, mobile app, etc).
Example of a bad design, as we're refactoring at $dayJob for example, is that when the internal API was first built, some responses had source instead of data, some did use data, some used the name of what the collection contained, users for example.. this highlights inconsistency as you don't know what a response is going to contain, it's different, randomly, for various endpoints.
Hope this clarifies some things.
Please or to participate in this conversation.