minaremonshaker's avatar

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

0 likes
12 replies
minaremonshaker's avatar

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)

ian_h's avatar

There is no "standard" for JSON responses (unless you go with the likes of the JSON:API), so really it's down to you to decide what you want from the response.

The biggest tip I would give, is to make all responses consistent and to use HTTP status codes correctly.

I would say skip the often used status property that I see added in many APIs unfortunately, this is what the HTTP status code should be defining. I do normally at least stick with the "standard" convention of wrapping collections of data in a data property, and skip this for single entities (ie: a call to an index route where there might be one or more items, wrap it, a show route where there is only one, I tend not to).

Also depends if you want to include more data in a single response. JSON:API keeps things "light" as such, but means there's multiple requests to make for the likes of relationships, where as you might decide the best approach for your case is to include relationships in your initial response.. again, this all depends largely on the data you're returning and how you decide you want to architect it, there is no "right or wrong" way to do that, as long as you're consistent.

Creations and updates are a little different as these will largely depend on the model definitions with regards to properties/fields and unless you're allowing bulk creations/edits, you're only going to be dealing with single entities at a time.

minaremonshaker's avatar

can i know what do you mean by consistent in here with an example if you don`t mind ?

jlrdw's avatar

JSON is handled behind the scenes on a post method. Go to the Axios JS website and look over examples.

I normally try to have the least amount possible of nesting in a JSON return to make it simple.

As far as looping over a JSON return, myself and others have past post that explain this in detail.

But do you even need an API, would a regular web app be better suited?

minaremonshaker's avatar

I’m learning how to create APIs because I want to integrate them with Vue.js. Personally, I find frameworks like Vue or React more flexible than Blade, especially since they give me greater control over JavaScript and regular HTML.

ian_h's avatar
ian_h
Best Answer
Level 20

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 message field with similar content
  • Both contain a data element wrapping around multiple entities
  • Both contain a pagination object

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 data property
  • 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.

martinbean's avatar

@minaremonshaker I don’t really know what you want?

JSON:API is a standard. If you want to follow the standard, then that’s the “shape” you use for requests and responses. If you don’t like it, then don’t use it. But if you are wanting to actually follow the standard then that’s what you should do.

The standard exists because it accommodates 99% of what you encounter in a RESTful API: resources with attributes, resources with relations, and optional metadata.

If you decide you’re going to “adopt” a standard like JSON:API but then decide to start breaking the rules of that standard because you decided it was too “complex” then there was no point using the standard in the first place.

minaremonshaker's avatar

Hi Martin, I used it because I'm following Jeremy's course and he uses it as well. I just wanted to follow along with him, but in my opinion, it's quite complex. So that why I asked can I make more simple and follow the same standard

minaremonshaker's avatar

As you saw above, some developers say there’s no standard, while others insist that you should follow one. This has confused me since it’s my first time creating APIs, and as you know , I’m used to follow the MVC pattern in all my previous projects.

martinbean's avatar

So that why I asked can I make more simple and follow the same standard

@minaremonshaker You’re no longer following the JSON:API standard if you “simplify” it and change what the standard dictates.

minaremonshaker's avatar

Ok , got the point thank you very mush , its following the standard or not that it

LaryAI's avatar
Level 58

Certainly! The JSON:API specification provides a powerful, standardized way to structure your API responses, but it can feel verbose or complex, especially for simple use-cases or when you're just starting out.

1. You Don't Have to Use JSON:API

If you don't need all the advanced features of JSON:API (like relationships, includes, links, etc.), you can use a simpler structure that suits your app. The Laravel JsonResource allows you to return data in any shape you prefer.


Example: A Simpler Resource Response

If you want something straightforward, you might do:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'description' => $this->description,
        'status' => $this->status,
        'author' => [
            'id' => $this->author->id,
            'name' => $this->author->name,
        ],
    ];
}

And then POST/PATCH requests can be just as simple:

  • POST /api/tickets (Creating ticket)
{
    "title": "Title for the new ticket",
    "description": "Details...",
    "status": "open"
}
  • PATCH /api/tickets/1 (Updating ticket)
{
    "title": "Updated Title",
    "status": "closed"
}

2. Things to Consider

  • Consistency: Pick a style you like, but try to keep it consistent across your API.
  • Complex Relationships: If you end up needing to express complex relationships later, you may want to revisit JSON:API or another spec.
  • Document Your Payloads: Whichever structure you choose, document it for others/your future self.

3. Takeaway

You’re totally free to use a simpler response and request format! Here’s a minimal TicketsResource:

class TicketsResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'description' => $this->description,
            'status' => $this->status,
            // Optional: include author details if loaded
            'author' => $this->whenLoaded('author', function () {
                return [
                    'id' => $this->author->id,
                    'name' => $this->author->name
                ];
            }),
        ];
    }
}

In summary:
You can absolutely stick to a simpler, flatter payload structure. JSON:API is optional in Laravel, and it's totally fine to use a less complex approach for your project!

Please or to participate in this conversation.