Search code examples
jsonapirestresponse

Is it necessary to have a set of objects nested in a named object


What is the right way to format your responses in JSON and why? I've seen different services do it two ways, consider a simple GET /users resource:

{
    "success": true,
    "message": "User created successfully",
    "data": [
        {"id": 1, "name": "John"},
        {"id": 2, "name": "George"},
        {"id": 3, "name": "Bob"},
        {"id": 4, "name": "Jane"}
    ]
}

That is how I usually do that. I have some abstract helper fields like success and message, there may be some more but the question is if should I nest the data in the data field to an array called the same way as the resource - users:

{
    "success": true,
    "message": "User created successfully",
    "data": {
        "users": [
            {"id": 1, "name": "John"},
            {"id": 2, "name": "George"},
            {"id": 3, "name": "Bob"},
            {"id": 4, "name": "Jane"}
        ]
    }
}

Even if we don't use the abstraction:

{
    "users": [
        {"id": 1, "name": "John"},
        {"id": 2, "name": "George"},
        {"id": 3, "name": "Bob"},
        {"id": 4, "name": "Jane"}
    ]
}

Seems the users key is obsolete as any client will know the route they called, which consists of /users, where users are mentioned, and the client code like

$users = $request->perform('http://this.api/users')->body()->json_decode();

looks much better than

$users = $request->perform('http://this.api/users')->body()->json_decode()->users;

as it avoids repeated users.


Solution

  • One use case where the envelope can be useful is when you are expecting to be dealing with large lists and need to do pagination to prevent huge response payloads. The envelope is a good place to put the pagination meta data:

    {
        "users": [...],
        "offset": 0,
        "limit": 50,
        "total": 10000
    }
    

    (This is what we do in a RESTful API I'm working on)

    Clearly this is only relevant for requests that return lists of things (e.g. /users/) and not for requests that return single entities (e.g. /users/42) and even for requests that return lists, you don't have to use an envelope - one alternative would be to use response headers for this meta data instead.

    PS. I would only advise having a success and message fields if you have a concrete use case for them. Otherwise don't bother, they are simply unnecessary.