REST convention for parent insert and parent + joinId insert using same endpoint

53 views Asked by At

In context of an event management system where speakers are talking at different sessions. My entities are Speakers and Sessions

Let's say the endpoint is

1) POST /speakers (to insert detail of a speaker ONLY)

2) POST /speakers (to insert detail of speaker + id of the session he's talking on)

point 2 requires to do an additional insert in the join table.

How can I specify both kinds of operations within the same endpoint.

1

There are 1 answers

4
AudioBubble On BEST ANSWER

A speaker could be represented including the session he speaks on. For example:

{
  "id": 1234,
  "firstname": "Joe",
  "lastname": "Doe",
  "sessions": []
}

This representation means that the speaker is not speaking on any session. sessions is an empty array. Doing

POST /speakers
Content-Type: application/json

with the JSON body as show above, would create the speaker.

If the client knows in advance all sessions the speaker will be speaking, the JSON could look like this:

{
  "id": 1234,
  "firstname": "Joe",
  "lastname": "Doe",
  "sessions": [
    {
      "id": 12,
      "link": "/session/12"
    },
    {
      "id": 34,
      "link"; "/session/34"
    }
  ]
}

For each session the speaker is speaking on, a short object consisting only of the id and a link to the session are included. This should be enough for the server to know how to link speaker and sessions in the database.

Now let's consider the case, that the sessions a speaker will speak on are not known in advance by the client. The client would create the speaker using the first JSON representation above including an empty sessions array. Later, when all sessions the speaker will speak on are known to the client, he would make a PATCH request:

PATCH /speakers/1234
Content-Type: application/json

{
  "sessions": [
    {
      "id": 12,
      "link": "/session/12"
    },
    {
      "id": 34,
      "link"; "/session/34"
    }
  ]
}

Note that now we only send the sessions. All other attributes of the speaker shall be left as is on the server.

If the client wants to add sessions to the speaker one after the other, he could do this for every session:

POST /speakers/1234/sessions
Content-Type: application/json

{
  "id": 43,
  "link": "/sessions/43"
}

This would mean: "add session 43 to the list of sessions of speaker 1234". here /speakers/1234/sessions is a sub resource of /speaker/1234. Adding to it makes sense (of course the server would have to check for duplicates).

Note the different usage of POST to create a new resource (a speaker), to add to a sub resource (the list of sessions). Note also that changing only part of a resource (the speaker) uses PATCH.

Edit:

The HTTP verb PUT is usually used if the client wants to send the complete representation of a resource. When adding the list of sessions to an existing speaker, we use PATCH on the speaker because using PUT on him would require the client to send a complete representation of the speaker. In this use case the client does not want to do this, he wants to set the list of sessions.

An alternative way could be to

PUT /speakers/1234/sessions
Content-Type: application/json

[
  {
    "id": 12,
    "link": "/session/12"
  },
  {
    "id": 34,
    "link"; "/session/34"
  }
]

with a complete list of sessions on the subresource sessions. Note the difference: here the client is sending a complete representation of the list of sessions for the speaker. Here PUT means: "Overwrite the complete list of sessions for this speaker with what I provide".

Using /speakers?eventId=1 to get the list of speakers for even 1 is good practice. Here the client requests a filtered subset of the collection resource /speakers. Using query parameter to express filter conditions is very common.

About good resources for this kind of knowledge my general advice is to always think about resource. What are the resources your API provides? How are different types of resources related? Can they exist next to each other (a speaker can exist without a session, a session can exist without a speaker), or are the composites (a hotel room can only exist inside a hotel). Usually this kind of question helps. But in REST there are no hard rules or "standards" for how URLs must be constructed. I think it is important to be consistent in an API.