I'm somewhat confused about which RESTful design is better.
For the API I have three types; Question
, Answer
and Student
. The Question
type has two subtypes; MultipleChoice
and Open
. The Question
type will possibly have more subtypes in the future. Note that the subtypes have common and distinct (optional) properties. Answer
is applicable to all questions.
I have seen similar questions (Modeling Object Inheritance in a REST Api, How to model a RESTful API with inheritance?), the given answers point to using a generic URL and specify a type in the body. However I do not feel as if the answers are authoritative (no reference to best practices, not a lot of upvotes, etc).
I'm looking for an authoritative, credible answer based on facts, not opinions.
I'll explain the possible designs below.
Type in URL
Requesting a list of all questions could be possible using GET /questions
. This would return a JSON list containing a summary of questions:
[
{
"url": "http://example.com/questions/multiplechoice/1",
"name": "example question"
},
{
"url": "http://example.com/questions/open/2",
"name": "another question"
}
]
Requesting a list of multiple choice questions is possible using GET /questions/multiplechoice
.
Creating a new multiple choice question is possible using POST /questions/multiplechoice
Server side these URLs map to different request handlers. The benefit of this is that there is no inspection necessary to check what type is to be created/returned, it is implied in the URL.
The downside of this approach (I think) is that when a student submits an answer the URL would be different for questions. POST /questions/multiplechoice/1/answers
and POST /questions/open/2/answers
.
Type in body
Requesting a list of all questions stays the same, GET /question
. The output would also be the same.
Requesting a list of multiple choice questions would mean filtering so this will be GET /questions?type=multiplechoice
.
Creating a new multipe choice question would mean also posting the type. The POST data would be:
{
"type": "multiplechoice",
"name": "example question"
}
The benefit would be that the URL remains simple and is less likely to change in the future. The downside is that one request handler needs to dispatch (using a mapping of some kind) requests based on body to other handlers specific to that type.
Answers are submitted using a universal URL: POST /questions/:question_id/answers
Type in header
The Content-Type
and Accept
headers can be used instead of the type
parameter.
To get a list of all questions: GET /questions
.
To get a list of all multiple choice questions: GET /questions
, Accept
set to application/app.multiplechoice+json
.
This approach is similar to the type-in-body approach. The extra downside is that this involves custom mime types, which are not really obvious if you ask me.