Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is best practice to serialize foreign key fields in a REST-ful api

I want to write a Django app with a REST-ful api. Django REST framework offers three built-in model serializers: ModelSerializer which serializes to something like this

{
    'normal_field': 'value',
    'foreign_key_field': 42
}

and HyperlinkedModelSerializer which serializes to something like this

{
    'normal_field': 'value',
    'foreign_key_field': 'http://domain/api/myothermodel/11'
}

My question is whether there is another good way to serialize the data so that the client directly knows which fields have to be resolved and which fields not.

Example: A client which receives this

{ 
    'foo': 'http://domain/api/myothermodel/11',
    'bar': 'http://otherdomain/api/myothermodel/12'
}

does not know whether foo or bar should be a resolveable foreign key field and not a plain url. Something like:

{ 
    'foo': 'http://domain/api/myothermodel/11', # Here the client might know that this is only a plain url.
    'bar': {
            '_foreignkey': true,  # Tells the client that this field should behave as a foreign key which has to be resolved first
            'url': 'http://otherdomain/api/myothermodel/12'
        }
}

Is there any standard or best practice? Or is best practice that the client does not know this from the JSON but from other code it has or gets from the server?

Update: Optional you can add which way is best practice for some wellknown client side libs like AngularJS.

like image 356
Norman8054 Avatar asked Sep 08 '14 17:09

Norman8054


1 Answers

It appears you are after a self-describing and explorable web API service, which is actually a core feature of the original REST concept referred to as Hypermedia as the Engine of Application State (HATEOAS). Essentially, a HATEOAS-compliant web service does not rely upon any prior knowledge of the system's resources other than the initial URL entry point.

This is in contrast to a Service Oriented Architecture (SOA) where individual services are basically unassociated and require prior knowledge of their existence to string together several service calls to accomplish some task with multiple, possibly related resources.

Most references to a REST API are actually not fully RESTful, and should more accurately be described as web APIs, as they are more in-line with the SOA design: a set of URLs to both specific instances and collections of instances of a particular type. This would also include the use of different HTTP verbs (GET, PATCH, POST, PUT) for various actions to perform on those resources. The Django REST Framework (DRF) actually has a page on this topic with links to some great resources on the true RESTful design, including the dissertation by Roy Fielding:

http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas

I would speculate that the current use of the term "REST API" relates to the revelation of many developers that implementing a truly RESTful service is far from trivial and in many cases would be over-engineered for the particular use case. Perhaps this is a good example of "perfection as the enemy of the good." For the case of using AngularJS as a client-side framework for interacting with a Django backend via DRF, this is especially true. There is nothing in the AngularJS framework that parses a truly RESTful design to automagically provide the various application states possible for a given resource. Plus, the same developer(s) will usually be responsible for both the JavaScript and Python code, so the lack of a self-describing API is not a major barrier to development.

Regarding the implementation of a truly RESTful API in JSON, there are a couple projects attempting to facilitate this, namely the Hypertext Application Language (HAL) and JSON Linked Data (JSON-LD). However, I am not aware that DRF natively supports either of these, so you would likely have to architect your serializers to conform to one of them, or roll your own Django REST implementation.

Finally, whatever design you choose, fully documenting the API is usually a good idea. This is true regardless of whether the API is web-based or in some native programming language. Part of the allure for the separation of concerns that a web API provides is that 3rd parties can consume resources to build applications or pipelines that you haven't considered, not to mention the advantages in maintainability for future changes to the code base for your project. There are a couple interesting projects mentioned on the DRF site to assist in documenting an API. Swagger is a particularly awesome one, developed by the same developer that provided the older Django REST Framework Docs package.

like image 197
Fiver Avatar answered Nov 15 '22 23:11

Fiver