Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle when REST resources are linked to and extending already existing resources?

Tags:

rest

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."
}
like image 500
horte Avatar asked Apr 24 '12 13:04

horte


1 Answers

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.

like image 120
jayraynet Avatar answered Sep 27 '22 16:09

jayraynet