I'm using swagger to prototype a RESTful API and I got to a situation where one property is part of a resource but not always should be filled.
Let's say my resource is stores
.
Basic endpoints would be:
GET: /stores
- returns a list of store
GET: /stores/{storeId}
- returns a single store
Say store is defined along the lines of:
Store {
id: integer,
name: string,
pictures: array[]
}
But when returning the list of stores, also returning every store's list of pictures is overkill. Pictures should be only returned for a single store request.
I'm confused on how to model that situation. On swagger, both methods responses are associated with a store
object.
Should I split store
into two objects and definitions so that each method return a different type even though only one property is different?
Should I use a query string parameter so that the consumer can choose whether or not pictures should be filled? Something along the lines of:
GET: /stores?fillPictures=false
or maybe
GET: /stores?detailed=false
When choosing the second option, the definition of a single store
would be the same no matter which endpoint is being accessed. That would mean an empty property would be transmitted to the consumer for every non detailed (with pictures) request. Should that be a concern?
Can someone shed some light on how to handle this scenario in a RESTful way? Maybe you know some API with a similar operation?
Thanks in advance.
2 Answers 2
GET: /stores - returns a list of store
GET: /stores/{storeId} - returns a single store
These are two different resources (a store, and a list of stores), so it is fine that they have different data.
The resource representing a list of stores can contain just enough information for the client to navigate to the store it might want. So it might be something like
Request
GET /stores
Response
200 - OK
{
stores: [
{id: 34, name: "Walmart", url: "/stores/34"},
{id: 35, name: "Best Buy", url: "/stores/35"}
]
}
The client can then navigate to the individual store to get any further information it needs about a particular store.
-
2You can calibrate this to precisely meet your needs:
/stores
could include one thumbnail picture, and then/stores/{storesId}
or/stores/{storeId}/pictures
could provide every available picture, with that link included in your first response.Gaurav– Gaurav01/11/2017 18:40:41Commented Jan 11, 2017 at 18:40 -
You're right. Different resources. @Gaurav what you wrote is exactly how i'm going. I was hanging too much on the fact that my swagger specification would have two very close definitions but I guess that's ok.Rodrigo Lira– Rodrigo Lira01/12/2017 14:11:40Commented Jan 12, 2017 at 14:11
-
1@RodrigoLira - I think that you've identified a key point in your comment. Do not conflate a clean swagger spec with a well designed API.D.Shawley– D.Shawley01/13/2017 13:03:14Commented Jan 13, 2017 at 13:03
If you have a many/many relationship (ie. a picture can go with mutiple stores) I would go with
Store {
id: integer,
name: string,
pictureIds: array[]
}
and a separate endpoint
POST: /getPictures pictureIds: array[]
If its a one store per picture relationship :
Store {
id: integer,
name: string
}
POST : /getPicturesForStores storeIds : array[]
Both these methods allow you to get a list of stores, and display all the pictures related to that list in two requests without duplicating data.
POST is required for 'get many' style requests as there is prohibitively small limit on the number of characters allowed in a url query string
pictures
array contain actual picture data or links where the pictures can be obtained when needed?