60

I'm currently coding an API for a social network with the Slim Framework. My question is: What are the best practices when there are no rows to return in the json structure?

Lets say that this call /v1/get/movies returns 2 rows from the table movie names:

[
    {"name": "Ghostbusters"},
    {"name": "Indiana Jones"}
]

But, then I call /v1/get/books and there are no rows in that table. Should I just return an empty structure?

[
]

...or would it be better a message and an error code?

[
    "errors": {
        "message": "no matches found",
        "code": 134
    }
]

Which is a better practice? (the API will be used in iOS and Android apps) Thanks!

Andres SK
  • 703
  • 1
  • 5
  • 7

14 Answers14

108

Your example is broken. You shouldn't have json objects with duplicate keys. What you are looking for is an array with movie objects, like this:

 [
    {"name": "movie1"}, 
    {"name": "movie2"}
 ]

This approach also answers your question. You should return an empty array when the query does not match:

[]

On the other hand, if you try to get a specific movie resource with GET api/movie/34 and that movie does not exist, then return 404 with a suitable (json encoded) error message in the body

Martin Wickman
  • 13,305
  • 3
  • 31
  • 66
51

Usually I would return number of records in result as metadata. I am not sure if that is normal REST practice, but it is not much extra data, and it is very precise. Usually there is pagination for lots of services, it is impractical to return huge resultset at once. Personally I am annoyed when there is pagination for small result sets.. If it is empty, return number_of_records : 0 and books as empty list/array books : [].

{
    meta: {
        number_of_records : 2,
        records_per_page : 10,
        page : 0
    },
    books : [
        {id:1},
        {id:27}
    ]
}

EDIT (few years later): Answer from Martin Wickman is much better, here is "short" of explanation why.

When dealing with pagination always keep in mind possibility of contents or ordering changing. Like, first request comes, 24 results, you return first 10. After that, "new book" is inserted and now you have 25 results, but with original request it would come ordered in 10th place. When first user requests 2nd page, he would not get "new book". There are ways to handle such problems, like providing "request id" which should be sent with following API calls, then returning next page from "old" result set, which should be stored somehow and tied to "request id". Alternative is to add field like "result list changed since first request".

Generally, if you can, try to put extra effort and avoid pagination. Pagination is additional state which can be mutated and tracking such changes is error prone, even more so because both server and client need to handle it.

If you have too much data to process at once, consider returning "id list" with all results and details for some chunk of that list, and provide multi_get/get_by_id_list API calls for resource.

grizwako
  • 697
  • 5
  • 8
  • I believe this is the best way to treat results. Having 0 records is not an error, its 0 records, so the meta?number_of_records value should be standard for the rest of the calls. Thanks! – Andres SK May 29 '13 at 16:48
  • 1
    Huh, I wonder why this one isn't voted as highly as the other one. I like this more as it's giving both an empty list (that was supposed to be a list, right?) that you can blindly iterate over without special conditions, but also the metadata count as a way of saying, "No, we didn't gloss over an error for you, there actually were 0 results". – Izkata May 30 '13 at 03:37
  • 1
    -1 because the `books` parameter is an object but 'books' implies more than one and more than one implies array. The meta data is cool and all but ultimately I'd expect a collection of books to be an array of book objects; if there are no books just give me the empty array – Charles Sprayberry May 30 '13 at 04:50
  • 10
    Problem with this is that adding "number_of_records" does not provide any more information, it just adds redundancy and increases complexity. To signal an error, return a suitable http code + something in the body. – Martin Wickman May 30 '13 at 10:10
  • 1
    @cspray books is list, as Izkata pointed, my typo. – grizwako May 30 '13 at 14:33
  • 2
    @MartinWickman I did not want to pollute original answer with extra metadata, but in my experience, lots of services do not return all data straight away, but in "paginated" way. – grizwako May 30 '13 at 14:46
  • 1
    I really think that a get should either return the object or an array of them. If you want to provide more info, just use headers.. – Alkanshel Mar 24 '19 at 03:35
16

If this is JSON, you should really consider returning an Array of objects. This has many advantages including that when you have no records it is an empty array.

So when you have records, you would be returning:

    [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]

And when you have no records, you would be returning:

    [

    ]
Devdatta Tengshe
  • 2,514
  • 4
  • 21
  • 22
14

If you execute operation successfully, but it doesn't have anything to return, such as empty map {} or empty array [] I would prefer to respond with 204 response code, here is excerpt from HTTP Status Code Definitions spec:

The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.

If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view.

The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.

Essentially, I recommend using 204 in RESTful applications over HTTP when there is nothing to return.

David Sergey
  • 513
  • 3
  • 11
  • 5
    I agree with @avakar's comment on other answer here. If the client's trying to access /v1/get/movies/1 then it should return 404 if there's no movies identifiable by 1. Just /v1/get/movies should return 200 even if there's no movie. But 204 isn't suitable because it's intended for input actions. – imel96 May 30 '13 at 02:19
  • 9
    Another problem with this solution is that it will typically need special code in the client: If the response is an empty list, it can be parsed as JSON just like a normal response. If the response is an empty body, the JSON parser will likely complain (because an emtpy document is not valid JSON), so the client needs extra code to check for HTTP 204 and skip the parsing. – sleske Feb 06 '14 at 12:00
  • 8
    I believe this is a misreading of the intention of 204. 204 appears to be intended not for operations that expected content and failed to find any, but rather for operations that were successful and have *no intended return*. From Wikipedia: *"The server successfully processed the request, but is not returning any content. Usually used as a response to a successful delete request."* – XML Aug 18 '14 at 02:20
11

There has been a reasonable amount of work done on creating a standardised JSON API format.

Following the principles in that specification mean that all resources returned should effectively be "collections" (even when just a single resource is included). Following this would mean that your call to /v1/get/movies would return:

{
    "movies": [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]
}

Your call to /v1/get/books (which returns zero resources) would return:

{
    "books": []
}
Tim Blair
  • 111
  • 3
5

For your specific example, I would recommend that /v1/get/books should return HTTP 200 with an empty array.

If I'm reading your post right, your API intends to collect books. Metaphorically speaking, you have a bookshelf for books, a DVD rack for movies, and possibly other containers that you haven't mentioned here. Because you intend to collect books, /v1/get/books is your bookshelf. This means there's a valid resource there -a list of books- which happens to be empty in your specific example.

The reason I don't suggest returning HTTP 404 in this case is that the bookshelf is still there. There aren't any books on it at the moment, but it is still a bookshelf. If it weren't a bookshelf -if the API didn't intend to collect books, for example- then HTTP 404 would be appropriate. But because there's a resource there, you shouldn't signal that there isn't one, which HTTP 404 does. Therefore, I argue that 200 with an empty array (signifying the collection) is more appropriate.

The reason I don't suggest returning HTTP 204 is that this would suggest that "No Content" is the ordinary state of affairs: performing this action on this resource normally wouldn't return anything. That's why it's usually used as a response to DELETE requests, for example: the nature of deletion generally means that there is left nothing to return. The case is similar when it's used to respond to requests with the If-Modified family of headers: you only wanted content if the resource had changed, but it hasn't, so I won't give you any content.

But I argue that for GETting an empty-but-valid collection, HTTP 204 doesn't make sense. If there were items in the collection, then the proper representation would be an array of that data. Therefore, when there is no data there (but the collection is valid), the proper representation is an empty array.

The Spooniest
  • 2,160
  • 12
  • 9
5

You really should do only one of two things

Either Return a 200 (OK) status code, and an empty array in the body.

Or Return a 204 (NO CONTENT) status code and NO response body.

To me, option 2 seems more technically correct and keeping in line with REST and HTTP principles.

However, option 1 seems more efficient for the client - because the client does not need extra logic to differentiate between two (success) status codes. Since it knows that it will always receive an array, it simply has to check for whether it got none, one, or many items and process it appropriately

Vihung
  • 511
  • 5
  • 6
3

The first thing to consider, since you are building a RESTful API, is to return an appropriate response code. And the more appropriate response code to communicate that the request went through normally, but the requested resource is not available at the moment is the venerable 404.

If you design your API in such a way that it always returns a sensible response code, you might not even need to return a body when the resource was not found. That said, returning a body, especially a humanly readable one, can't hurt.

There's no "best practice" here, both your examples are arbitrary, just pick one and be consistent. Developers hate surprises, if /v1/get/movies returns {} when there are no movies then we'd expect /v1/get/actors to also return {} when there are no actors.

yannis
  • 39,547
  • 40
  • 183
  • 216
  • 1
    Returning a 404 really is the right thing to do, but sadly no one really does it-- myself included. – RibaldEddie May 29 '13 at 06:59
  • 1
    if you have complex responses, and only parts of them are empty, returning a 404 will confuse the user. – devnull May 29 '13 at 07:03
  • @devnull Well, yes, if you have more complex responses, a different response code might be more appropriate. However, one of the main purposes of a RESTful design is to map (simple) resources to URLs. I'm not so sure that overly complex responses are in line with the spirit of RESTful design. – yannis May 29 '13 at 07:06
  • medical tests can be one example of such complex responses and in most of the cases the requirement is that all the data is to be passed around in a single response. of course, the problem in the question is much simpler and attaching an HTTP status code to each response is suitable. – devnull May 29 '13 at 07:08
  • @devnull Oh, I can think of quite a few examples of complex responses, that wasn't my point. An API that typically returns overly complex responses is not really a RESTful one (a key principle of REST is the 1-1 relationship of a request with a resource, or a collection of similar resources). And that's perfectly fine, RESTful is not a silver bullet, not every API should be RESTful. – yannis May 29 '13 at 07:11
  • 5
    I would disagree with the 404 message. A 404 I would interpret as "resource does not exist" and worry if I got something wrong with my URL or whatever. If I ask for a list of movies and get a 404 I would think that there isn't a movie resource at all. A "204 No Content" may be more appropriate. – thorsten müller May 29 '13 at 07:15
  • 1
    @thorstenmüller That's a human response to an error code that's not intended for humans (the response body is what humans should read). 404 simply means the resource is not available at the moment (but feel free to try again), and that's about it. 204 No Content would be wrong here, as [204 responses must not have a response body](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html), and are always terminated by the first empty line after the header fields (I'm assuming the OP wants a response body, because... that's what the question is about ;). – yannis May 29 '13 at 07:20
  • well, if you get a 404 there's nothing usable in the body anyway – devnull May 29 '13 at 07:27
  • @devnull Exactly. That's what the question is about: What to return when you have nothing to return. – yannis May 29 '13 at 07:28
  • 8
    Ok, the "no body" thing would kill it. But: "The 4xx class of status code is intended for cases in which the client seems to have erred.". But there was no error on the client side. So a 404 gives wrong information. Either send 204 without a body or say it's ok and send an empty list. – thorsten müller May 29 '13 at 07:29
  • @thorstenmüller I wouldn't mind a 200 + empty list. Returning a 200 on a request that technically hasn't been fulfilled doesn't feel quite right, but I can understand the arguments against 404. – yannis May 29 '13 at 08:03
  • 9
    You're asking for a list of books, returning 404 would mean that *the list* doesn't exist, not that it is empty. Returning 200 along with an empty list seems the only reasonable option to me. – avakar May 29 '13 at 17:47
3

I've seen both cases in production environments. Which one you choose depends on who will be using the API. If they want to know why the list is empty or to be sure that the list is really empty and no errors occurred while retrieving it, then you should attach an "errors" object. If they don't care, go with returning an empty list. I'd go with second approach since it covers more needs than the first.

devnull
  • 2,969
  • 20
  • 20
1

I don't think the rigth answer is the one that is marked.

The answer provided by nirth should be the best, in a true REST scenario. The body response should be empty and the http status code: 204; the resource does exists but it has "no content" at that time: is empty.

REST HTTP_Status_Codes

1
  • First of all, having get in your URL is not RESTful, GET is implied by the HTTP method.
  • If you're requesting a collection like GET api/movies return a 200 OK with an empty array [].
  • If you're requesting a specific movie like GET api/movies/1 (where 1 is the id) and it doesn't exist, return a 404 Not Found.

Why? You are requesting resources. When you are requesting the collection, the resource itself (the collection) exists. Therefor, a 404 is wrong. But if you request a specific movie and it doesn't exist, the resource requested doesn't exist, and you have to return a 404.

felixfbecker
  • 119
  • 1
1

I recommend 200 + empty array, since it simplifies the handling by all the clients of the API. 200 + array means "I returned all the data that is there". Both to the code delivering the data and the code processing it, the number of items would be irrelevant.

Every other status code needs to be properly documented and properly delivered by the server and properly processed by the client, and we all know how likely this is to happen.

There was a suggestion to return status 204 + empty body. That means you force every single client to process status 204 correctly. Moreover you force them to handle non-JSON replies! I hope everyone realises that just because a request got an answer, it doesn't mean the answer came from the server when http is used, and just a check that the response is JSON handles many of those cases.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
0

I would "It depends".

If zero is a reasonable result then return the empty list. For example if you want to get all employees called "bob" where "none" is a quite reasonable result. If it's not an expected result return an error. For example getting a historical list of street addresses for a person you employ.. They must live somewhere so no result is probably an error, not just a normal condition.

I'm sure you can argue with the specifics of my example, but you get the idea...

JohnB
  • 1,231
  • 2
  • 8
  • 10
-2

If you are returning JSON , it is better to always return count and error message and maybe a Boolean that indicated if there is error or no , that is my standard three meta values returned with each list of rows .

sino
  • 105
  • 6