六月 16, 2018 | 後端和Drupal

Decouple系列:要用 JSON API 還是 REST API呢?

隨著專案的進行,原本使用原生API進行Decouple網站製作開發的我們,也開始發生API製作出來有時KEY不同、欄位不同、或格式不同的情況。儘管修改容易,但是依照工程師凡事都想要越來越簡單的個性,我們開始轉移到JSON API的使用,以長遠來看,一套好的標準在團隊內,還真是件開心且容易的事情。

前言

在Drupal的架構中,若要製作REST API,在D7當中則是使用Services這個模組,而到了D8,這個模組則是原生整合到了核心Core裡面。D8使用REST,使用上面變得更強大與方便,但同樣你應該也有注意到另外一個模組,就是JSPN API,使用上面同樣也讓人驚艷。這篇文章將來做一個簡單的比較,供大家參考。

ps:若你想要直接瞭解其詳細差異,也可以直接跳看【綜合比較】

D8核心Views+REST【API建立完全客製化】

各位一定都知道,Drupal是以極大彈性為著稱的CMS,有了Views這個模組,可以讓我們操控資料隨心所欲,若您還不是這麼瞭解Views,可以參考這篇文章Drupal新手教學:Drupal必學模組Views介紹-part1,而到了D8將Services模組整合到核心後,更是跟Views整合,讓API的彈性發揮到極致。

幾項優點整理如下:

  1. 整合在核心模組裡面 在D8的環境下,只需要直接啟用以下的幾個核心模組即可,不需要額外再安裝其他模組。核心模組也代表者穩定性與支援度都非常的好,比較不會因為版本的升級,而造成模組使用上的問題

  2. 使用Views可以自行客製所有的API欄位 使用Views來製作API的方式跟一般我們常用一樣,這個是所有Drupaler的福音。所以製作API上面變的輕鬆寫意,可以很容易在很短的時間內,製作出任何你想到的API。

JSONAPI模組【隨裝隨用、免設定、免開啟REST、彈性一樣沒問題】

JSONAPI模組其實是依照JSONAPI的規則所建置。那什麼是JSONAPI呢?簡單來說「JSONAPI就是提供JSON格式API介面的標準化,讓大家都遵照一樣的規則來走,如此以來所有的工程師都可以直接把時間專注在程式開發上面」。

相較起來,D8環境提供的是製作API的絕對彈性,那麼JSONAPI模組,則是提供了一個標準化的JSON-API格式,完全不用再製作API,直接照者其提供的規則走即可。

若您還不是這麼清楚或沒有聽過jsonapi。可以參考以下連結

幾項優點整理如下:

  1. 隨裝隨用、免設定 不同於D8的絕對彈性,JSONAPI安裝完成以後,就可以用了,只需要在網址輸入"http://yourdoman.com/jsonapi",就可以發現整個Drupal網站資料,一覽無遺。可以再根據你的需求,參考JSONAPI規則,即可做出你所想要的各種API。
    • 以下是回傳格式的範例
    {
      "links": {
        "posts.author": {
          "href": "http://example.com/people/{posts.author}",
          "type": "people"
        },
        "posts.comments": {
          "href": "http://example.com/comments/{posts.comments}",
          "type": "comments"
        }
      },
      "posts": [{
        "id": "1",
        "title": "Rails is Omakase",
        "links": {
          "author": "9",
          "comments": [ "5", "12", "17", "20" ]
        }
      }]
    }
    
  2. API規則標準化 若使用原生的API,彈性極大,但往往會因為每個工程師製作的方式不同而不好管理。隨者API數量與專案數量越來越多,會造成越來越多的問題。若使用JSONAPI,將會讓這個問題不再出現,若是要開發一個大型的前後端分離專案,是個非常好的選擇。並且,也讓非Drupal的工程師,能夠用這個標準規格,跟Drupal網站進行銜接。

綜合比較

以下為官方網站提供的綜合比較 <table border="0" cellpadding="1" cellspacing="1" summary="summary"> <thead> <tr> <th scope="row">Feature</th> <th scope="col">JSON API</th> <th scope="col">REST</th> <th scope="col">Remark</th> </tr> </thead> <tbody> <tr> <th scope="row">Entities exposed as resources</th> <td>✔️</td> <td>✔️</td> <td>REST: need to configure this per entity type. JSON API: everything exposed by default. Both: respect entity access.</td> </tr> <tr> <th scope="row">Custom data exposed as resources</th> <td></td> <td>✔️</td> <td>Write custom @RestResource plugins. JSON API only supports entities.</td> </tr> <tr> <th scope="row">Getting individual resources</th> <td>✔️</td> <td>✔️</td> <td></td> </tr> <tr> <th scope="row">Getting lists of resources</th> <td><a href="http://jsonapi.org/format/#fetching-resources">✔️</a></td> <td>kinda</td> <td> <p>REST: need to configure a view, and set up a "REST export" display.</p> </td> </tr> <tr> <th scope="row">Paginating list of resources</th> <td><a href="http://jsonapi.org/format/#fetching-pagination">✔️</a></td> <td></td> <td>REST: not supported! REST export views return&nbsp;<em>all</em>&nbsp;resources.</td> </tr> <tr> <th scope="row">Filtering list of resources</th> <td>✔️</td> <td>kinda</td> <td> <p>REST: only if you create an exposed filter for every field, and every possible operator</p> </td> </tr> <tr> <th scope="row">Sorting of resources</th> <td><a href="http://jsonapi.org/format/#fetching-sorting">✔️</a></td> <td></td> <td></td> </tr> <tr> <th scope="row">Includes/embedding</th> <td><a href="http://jsonapi.org/format/#fetching-includes">✔️</a></td> <td>Only in HAL+JSON</td> <td></td> </tr> <tr> <th scope="row">No unnecessary wrapping of field values</th> <td>✔️</td> <td></td> <td>Both the HAL normalization and the default normalization (and hence&nbsp;<em>all</em>&nbsp;formats) suffer from exposing exactly the in-memory PHP data structures that Drupal uses, causing painful DX for consumers. JSON API simplifies the normalization of single-cardinality and single-property fields.</td> </tr> <tr> <th scope="row">Ability to omit fields consumer does not need</th> <td><a href="http://jsonapi.org/format/#fetching-sparse-fieldsets">✔️</a></td> <td></td> <td></td> </tr> <tr> <th scope="row">Consistent URLs</th> <td>✔️</td> <td></td> <td></td> </tr> <tr> <th scope="row">Consumer can discover available resource types</th> <td>✔️</td> <td></td> <td></td> </tr> <tr> <th scope="row">Drupal-specific response structure</th> <td><a href="http://jsonapi.org/format/#document-structure">✔️</a></td> <td></td> <td>REST: the HAL normalization in theory is void of Drupalisms, but in practice it isn't.</td> </tr> <tr> <th scope="row">Client libraries</th> <td><a href="http://jsonapi.org/implementations/">✔️</a></td> <td></td> <td></td> </tr> <tr> <th scope="row">Extensible spec</th> <td><a href="http://jsonapi.org/extensions/">WIP</a></td> <td></td> <td></td> </tr> <tr> <th scope="row">Zero configuration</th> <td><a href="http://jsonapi.org/implementations/">✔️</a></td> <td></td> <td>REST: each @RestResource plugin definition is available to be exposed, but must be configured to be exposed. For each, you must select the allowed formats, allowed authentication providers and optionally even allowed HTTP methods.<br /> JSON API: all entities are exposed automatically, entity/field access is respected, all installed authentication providers are allowed automatically.</td> </tr> </tbody> </table>

結論

我們團隊在開發時,一開始是使用原生的API在進行Decouple網站的製作,但是隨著專案的進行,開始會發生API製作出來有時KEY不同、欄位不同、或格式不同的情況。雖然,修改上面是非常容易的,但是依照工程師凡事都想要越來越簡單的個性,我們開始轉移到JSON API的使用。雖然一開始要熟悉新的規範,但是以長遠來看,一套好的標準在團隊內,是件開心且容易的事情。

參考資料

  1. https://www.drupal.org/docs/8/modules/json-api/comparing-json-api-and-cores-rest-module