Search code examples
restapi-design

Design of REST methods for both deep and shallow insert options


We are designing REST API and having course and student entities:

  • course includes multiple students
  • multiple courses may share the same student
  • when creating course one should be able to both include already existing students(shallow insert) and refer existing(deep insert).

Which is most intuitive and correct option:

  1. Have both options for providing ids and bodies on parent level:
POST /courses
{
  "courseName" : "Java 8",
  "students" : [
    {
      "name" : "John Doe" // new student(deep insert)
    }
  ],
  "studentIds" : [
    123, 124              // existing students(shallow insert)
  ]
}
  1. Have both options for providing ids and bodies on child level:
POST /courses
{
  "courseName" : "Java 8",
  "students" : [
    {
      "name" : "John Doe" // new student(deep insert)
    },
    {
      "studentId" :123    // existing student(shallow insert)
    },
    {
      "studentId" : 124   // existing student(shallow insert)
    }
  ]
}

Is this only design choice for this case?

Is it acceptable to have ambiguity for JSON when fields for both id and payload are present in child entity, like in student entity above?

This is behind what is usually covered by REST guidelines and other asked questions here.


Solution

  • As far as REST is concerned, both request payloads are fine. REST doesn't constrain the representations that are sent across the network.

    An analogy that may help: on the web, we typically send information to web servers via forms, and we've got a standardized mechanism for copying information from form controls into the request body; but there aren't any rules saying "you must design your form this way".

    So if you want to mix complete representations of students with digest representations of students, that's fine. And if you prefer to separate them out, that's also fine.


    The right place to look for guidance isn't REST (which, again, doesn't care what your documents look like), but rather the principles of message schema design.

    In particular, you'll want to be paying attention to whether or not the schema can be extended in a backwards compatible way, whether you can communicate/describe the schema unambiguously, and whether you can process the schema without ambiguity.

    My guess: your life will be easier with the first schema, because you are avoiding needing to interpret whether a particular JSON Object is complete or digest - you "know" the answer to that based on which list the object is in.

    Useful references on message design include:

    • Greg Young's Versioning in an Event Sourced System
    • David Orchard's work on XML Vocabularies
    • Kenton Varda's work on Protocol Buffers