Let's say we have schools with some data including a name and a list of students, and students with some data including courses they're enrolled in and a reference to their school. On the client:
Is there a good way to do all of this, or will some of the constraints have to be lifted?
A first approach would be to have an API that does something like this:
GET /school/1
{
id: 1,
name: "Jefferson High",
students: [
{
id: 1
name: "Joel Kim"
},
{
id: 2,
name: "Chris Green"
}
...
]
}
GET /student/1
{
id: 1,
name: "Joel Kim",
school: {
id: 1,
name: "Jefferson High"
}
courses: [
{
id: 3
name: "Algebra 1"
},
{
id: 5,
name: "World History"
}
...
]
}
An advantage of this approach is that, for each screen, we can just do a single fetch. On the client side, we could normalize schools and students so that they reference eachother with IDs, and then store the objects in different data stores. However, the student
object nested inside of school
isn't a full object -- it doesn't include the nested courses, or a reference back to the school. Likewise, the school
object inside of student
doesn't have a list of all attending students. Storing partial representations of objects in data stores would lead to a bunch of complicated logic on the client side.
Instead of normalizing these objects, we could store schools and students with their nested partial objects. However, this means data duplication -- each student at Jefferson High would have the name of the school nested. If the school name changed just before doing a fetch for a specific student, then we'd show the right school name for that student but the wrong name everywhere else, including on the "school details" page.
Another approach could be to design the API to just return the ids of nested objects:
GET /school/1
{
id: 1,
name: "Jefferson High",
students: [1, 2]
}
GET /student/1
{
id: 1,
name: "Joel Kim",
school: 1,
courses: [3, 5]
}
We'd always have "complete" representations of objects with all of their references, so it's pretty easy to store this information in data-stores client side. However, this would require multiple fetches to show each screen. To show information about a student, we'd have to fetch the student and then fetch their school, as well as their courses.
Is there a smarter approach that would allow us to cache just one copy of each object, and to prevent multiple fetches to show basic screens?
You might be mixing two concepts: Storage and Representations. You can give back a non-normalized representation (the first option you suggested) without also storing those "partial" object in your database.
So I would suggest to try to return non-normalized representations, but storing them normalized (if you are using a relational DB).
Also, an improvement suggestion: You may want to use proper URIs instead of Ids in your representations. You probably want the clients to know "where" to get that object from, it's easier therefore to just supply the URI. Otherwise the client needs to figure out how to produce a URI out of an Id, and that usually ends up being hard-coded in the client, which is a no-no in REST.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With