RESTful API design using HAL - model relationship serialization

I'm relatively new to REST, but I did my homework on how RESTful should be. Now I'm trying to create a RESTful api that implements the JSON + HAL serializer for my models that are related to other models.
Examples of models in python:

class Category(Model): name = CharField() parent = ManyToOneField(Category) categories = OneToManyField(Category) products = ManyToManyField(Product) class Product(Model): name = CharField() price = DecimalField() related = ManyToManyField(Product) categories = ManyToManyField(Category) 

suggests that we have a category “catalog” with a subcategory “food” with products “hamburger” and “hot dog” that are related to each other.
First question. Categories and products should be resources, so they need a URI, should I implement the uri field in my model and store it in the database or somehow calculate it at runtime, as for multiple identifiers (URIs)?
Second question. Openness, in Hal format, which should "GET /" and different nodes return so that the api can easily find itself.

 { "_links":{ "self":{ "href":"/" }, "categories":[ { "href":"/catalog" } ] } } 

Third question. Add as properties, insert or link. Example "GET / catalog / food":

 { "_links":{ "self":{ "href":"/catalog/food" } }, "name":"food", "parent":"/catalog", "categories":[], "products":[ "/products/burger", "/products/hot-dog" ] } { "_links":{ "self":{ "href":"/catalog/food" }, "parent":{ "href":"/catalog" }, "categories":[ ], "products":[ { "href":"/products/burger" }, { "href":"/products/hot-dog" } ] }, "name":"food" } { "_links":{ "self":{ "href":"/catalog/food" } }, "name":"food", "_embedded":{ "parent":{ "_links":{ "self":{ "href":"/catalog" } }, "name":"catalog", ... }, "categories":[ ], "products":[ { "_links":{ "self":{ "href":"/products/burger" } }, "name":"burger", ... }, { "_links":{ "self":{ "href":"/products/hot-dog" } }, "name":"hot-dog", ... } ] } } 

The fourth question. How hard I have to go, returning the structure. GET / catalog example

 { "_links":{ "self":{ "href":"/catalog" } }, "name":"catalog", "parent":null, "categories":[ { "name":"food", "parent":{...}, "categories":[], "products":[ { "name":"burger", "price":"", "categories":[...], "related":[...] }, { "name":"hot-dog", "price":"", "categories":[...], "related":[...] } ] } ], "products": [] } 
+6
source share
2 answers

About the first question : I would not save the URI in the database. You can easily compute them inside your controller at runtime, and it is the responsibility of the dispatcher to take care of the URI. This way you keep your model and your API untied, and if you decide to change the structure of the API in the future, you don’t need to update your entire database with new URIs.

About several identifiers, I'm not sure what the question is, but again, in my opinion, it has nothing to do with the database, its routing and controllers, which should take care of how to handle any URIs.

About the second question . First of all, as a note: I would save the categories of words as part of the URI. For example, I have http://domain.com/api/categories/catalog/food . Thus, you make your API more visible and more “hacked,” which means that the user should be able to remove the /catalog/food and wait for the collection to be received with all available categories.

Now that GET should come back in order to be able to detect: I think this is already clearly visible from your URI structure. When the user presses GET /categories , he expects to get a list with categories (name and URI for each so that it is easy), and when he follows one of the URIs, for example GET /categories/catalog , he should get the catalog resource, which is by category. Similarly, when he wants a GET /products/burger , he should get a product resource with all the attributes that you have in your model. You can check out this example about the structure of your answers.

About the third question : Again, the same example can help you shape the structure. I think your second answer is closer to this, but I would also add a name field, not just href .

About the 4th question : when a GET request expects a set of resources (for example, GET /categories ), I propose to provide only the necessary for each resource, that is, the name and URI for each and only when the user follows the desired URI, he can get information about the rest.

In your example, catalog is a resource, so on GET /categories/catalog I would, of course, include the name resource (directory) and its own link, and for parent , sub-categories and products that are associated with it, I would simply give the name and a URI for everyone to be bright. But . This was a general idea about developing an API. In your real problem you have to solve, depending on your specific business problem. I mean, if your API contains a restaurant menu with categories and dishes, you can include a price or a small description, even if you answer not to the actual product, but to the collection of products, because this is probably important information for your users. As a rule, provide all the necessary information (you only know that it concerns your problem) when responding to the list of resources and provide all the information about the resource when responding to a specific resource.

+6
source
  • I would save something in the database and compute the URI in Runtime. Thus, if you move boxes, it is not static.
  • Create a bookmark page. The page we created was just a list of links with our rels. I believe the HAL specifically defines this. The bookmark page was the only page to learn about
  • Not sure about it
  • How deep you go depends on you. At my place of work there is now a big debate on fine grain versus grain. I am going to make small grain with a small resource to support a simple api, but then use the Expand-ability concept. This is a combination of the composite resource idea defined on page 35 of the Subbus REST book and the extension concept used by Netflix. http://developer.netflix.com/docs/REST_API_Conventions
+1
source

All Articles