I am building a REST API where I have "Books" and "Users". Their can only exist one unique Book. Though a User can have several Books and different users can have the same Book (or reference to the same). A User can add additional information to a Book (e.g. rating).
My question is: What is a proper way to map the resources when Users are "extending" an already existing Book resource with their own settings?
Example: A first time user have no Books but they can create a Book. If the Book doesn't exist it is created, if it exists they get access to it. Though they can add their own private additional information to it.
Is this a proper way?
//All Books with the basic required information can be reached on /books/:id Example: /books/1
{
"id":1,
"title":"The Empire",
"description":"Description about the book",
"serial":1234
}
//If a User creates the book "The Empire" (serial: 1234) they are extending the already existing book but they have added additional information so it is actually a new URL but refers to the Book id.
Example: /users/421/books/1/
{
"id":1,
"title":"The Empire",
"description":"Description about the book",
"serial":1234,
"rating":5.5,
"note":"I liked the book but it was too long."
}
Or even:
{
"book": {
id":1,
"title":"The Empire",
"description":"Description about the book",
"serial":1234,
}
"rating":5.5,
"note":"I liked the book but it was too long."
}
Or even a URL smth like /users/421/books/1/settings/
{
"rating":5.5,
"note":"I liked the book but it was too long."
}
I would recommend allowing the "reviews" to be associated with multiple parents (book, user) and then having a canonical resource for the review as follows:
Book /books/{book-id}
{
"id":1,
"title":"The Empire",
"description":"Description about the book",
"serial":1234
}
Reviews of a book /books/{book-id}/reviews
{[
{
"id":1,
"userId":user1,
"bookId":1,
"rating":5.5,
"note":"I liked the book but it was too long.",
"url":http://server/reviews/1
},
{
"id":2,
"userId":user2,
"bookId":1,
"rating":1,
"note":"boo, i didn't like it!",
"url":http://server/reviews/2
}
]}
Reviews by a user /users/{user-id}/reviews
{[
{
"id":1,
"userId":user1,
"bookId":1,
"rating":5.5,
"note":"I liked the book but it was too long.",
"url":http://server/reviews/1
},
{
"id":2,
"userId":user2,
"bookId":1,
"rating":1,
"note":"boo, i didn't like it!",
"url":http://server/reviews/2
},
{
"id":5,
"userId":user1,
"bookId":3,
"rating":2,
"note":"I like to read",
"url":http://server/reviews/5
}
]}
Canonical resource for a review /reviews/{review-id}
{[
{
"id":1,
"userId":user1,
"bookId":1,
"rating":5.5,
"note":"I liked the book but it was too long.",
"url":http://server/reviews/1
},
{
"id":5,
"userId":user1,
"bookId":3,
"rating":2,
"note":"I like to read",
"url":http://server/reviews/5
}
]}
Creating a new review can be a post to the user/reviews, book/reviews, or reviews resources with the server implementation of those POST service defaulting user-id or book-id as appropriate.
The implementation of the url link has some choices such as atom:link.
Also, consider not exposing the raw id of books, users, and reviews to the client/consumer of these services, and instead exposing the id as a URI.
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