62

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!

2
  • 3
    To me this feels like the question whether zero is actually an amount.
    – scarfridge
    Commented May 29, 2013 at 8:14
  • 27
    If your application is meant to be RESTful, then why is the verb/method "get" a part of your endpoint URI?
    – user50849
    Commented May 30, 2013 at 7:20

14 Answers 14

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.

7
  • 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
    Commented May 30, 2013 at 3: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 Commented May 30, 2013 at 4: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. Commented May 30, 2013 at 10:10
  • 1
    @cspray books is list, as Izkata pointed, my typo.
    – grizwako
    Commented May 30, 2013 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
    Commented May 30, 2013 at 14:46
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

1
  • 1
    +1 This is valid JSON according to json_xs.
    – l0b0
    Commented May 29, 2013 at 11:03
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:

    [

    ]
0
15

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.

3
  • 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
    Commented May 30, 2013 at 2: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
    Commented Feb 6, 2014 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
    Commented Aug 18, 2014 at 2:20
12

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": []
}
6

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

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.

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.

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.

12
  • 1
    Returning a 404 really is the right thing to do, but sadly no one really does it-- myself included. Commented May 29, 2013 at 6:59
  • 1
    if you have complex responses, and only parts of them are empty, returning a 404 will confuse the user.
    – devnull
    Commented May 29, 2013 at 7:03
  • 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. Commented May 29, 2013 at 7:15
  • 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. Commented May 29, 2013 at 7:29
  • 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
    Commented May 29, 2013 at 17:47
3
  • 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.

2

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.

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

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...

-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 .

Not the answer you're looking for? Browse other questions tagged or ask your own question.