服務接口統一返回的格式GOOD

表達,從簡單開始。--《Robin Williams:寫給大家看的設計書》

1.14.1 統一返回的格式

很明顯地,默認情況下,我們選擇了 JSON 作爲統一的格式返回接口結果。這裏簡單說明一下選取JSON統一返回的原因:

  • JSON當前很流行,且普通接口都採用此格式返回
  • JSON在絕大部分開發語言中都支持,跨語言
  • JSON在瀏覽器瀏覽時,有可視化插件支持,如FF下:

    apic

1.14.2 統一返回結構

通常,我們正常情況下請求接口會返回類似:

{
    "ret": 200,
    "data": {
        "title": "Default Api",
        "content": "PHPer您好,歡迎使用PhalApi!",
        "version": "1.1.0",
        "time": 1423142802
    },
    "msg": ""
}

其中,ret表示爲返回狀態碼,200表示成功;data爲領域業務數據,由接口自定義;最後msg爲錯誤的提示信息。下面分別解釋之。

(1)返回狀態碼 ret

參照HTTP的狀態碼,特約定:

  • 200:接口正常請求並返回
  • 4XX:客戶端非法請求
  • 5XX:服務器運行錯誤

200 正常返回

當返回200時,需要同時返回data部分數據,以便客戶端實現所需要的業務功能。

4XX 客戶端非法請求

此類請求是由客戶端不正確調用引起的,如請求的接口服務不存在,或者接口參數不對,驗證失敗等等。當這種情況發生時,客戶端同學只需要調整修正調用即可。

對於此係統的狀態碼,在進行接口開發時,可由項目自已定義約定。 通常地,我們需要告知客戶端簽名失敗時,可以這樣:

throw new PhalApi_Exception_BadRequest('wrong sign', 1);

即拋出PhalApi_Exception_BadRequest異常即可,錯誤信息會返回客戶端,對應msg字段;狀態爲1,系統對此類的異常會在400基礎上相加的,即:401 = 400 + 1

5XX 服務器運行錯誤

此類錯誤是應該避免的,但當客戶端發現有這種情況時,應該知會後臺接口開發人員進行修正。
如當配置的參數規則不符合要求時,或者獲取了不存在的參數等即會觸發此類異常錯誤,通常由框架拋出。

(2)業務數據 data

data爲接口和客戶端主要溝通對接的數據部分,可以爲任何類型,由接口自定義。但爲了更好地擴展、向後兼容,建議都使用array。

返回格式的定義與在線查看

當我們在開發接口時,可以通過爲接口添加註釋的方式來定義接口的返回格式,然後就可以爲外部提供在線文檔的實時查看了。

如:

<?php

class Api_User extends PhalApi_Api {

    /**
     * 獲取用戶基本信息
     * @desc 用於獲取單個用戶基本信息
     * @return int code 操作碼,0表示成功,1表示用戶不存在
     * @return object info 用戶信息對象
     * @return int info.id 用戶ID
     * @return string info.name 用戶名字
     * @return string info.note 用戶來源
     * @return string msg 提示信息
     */
    public function getBaseInfo() {
        // ... ...
    }

然後在瀏覽器訪問:
http://demo.phalapi.net/checkApiParams.php?service=User.getBaseInfo

可以看到:
apic

註釋格式

格式是以docs的 return 註釋來標明的,其格式爲:

@return  返回的類型  字段名字路徑(以點號連接)  字段名字及解析

其中,返回的類型可以爲:

關鍵字 說明
string 字符串
int 整型
float 浮點型
boolean 布爾型
date 日期
array 數組
fixed 固定值
enum 枚舉類型
object 對象

溫馨提示:array與object的區別
array是指沒有下標的一個數組集合,或者有下標但下標是連續的自然數,且各元素的結構相同;object則是指一個結構體,類似字典。

此外,爲了明確數組與對象間的返回格式,我們也推薦如果是元素來自數組,則在返回字段的後面添加方括號來表明,以提醒客戶端在接收到此類返回時需要循環處理。如:

     * @return array list 用戶列表
     * @return int list[].id 用戶ID
     * @return string list[].name 用戶名字
     * @return string list[].note 用戶來源

當需要對接口進行更多說明時,可使用@desc註釋,即:

     * @desc 用於獲取單個用戶基本信息

(3)錯誤信息 msg

當返回狀態碼不爲200時,此字段不爲空。即當有異常(如上面所說的客戶端非法請求和服務端運行錯誤兩大類)觸發時,會自動將異常的錯誤信息作爲錯誤信息msg返回。

但對於服務端的異常,出於對接口隱私的保護,框架在錯誤信息時沒有過於具體地描述;相反,對於客戶端的異常,由會進行必要的說明,以提醒客戶端該如何進行調用調整。

此外,我們根據需要可以考慮是否需要進行國際化的翻譯。如果項目在可預見的範圍內需要部署到國外時,提前做好翻譯的準備是很有幫助的。如下,開發時可以這樣返回異常錯誤信息:

throw new PhalApi_Exception_BadRequest(T('wrong sign'), 1);

1.14.3 關於Exception類異常沒捕捉的原因

我們沒有對Exception類的異常進行捕捉,封裝返回非200的形式,是因爲我們出於以下的考慮:

  • 一來爲了方便開發過程中快速發現及定位具體出錯的位置;
  • 二來爲了便於線上環境中nginx服務器對錯誤的捕捉和紀錄;

1.14.4 JsonP格式和其他的返回

在部分H5頁面異步請求的情況下,客戶端需要我們返回JSONP格式的結果,則可以這樣在入口文件重新註冊response:

if (!empty($_GET['callback'])) {
    DI()->response = new PhalApi_Response_JsonP($_GET['callback']);
}

但是在測試環境中,我們是不希望有內容輸出的,所以我們可以測試時這樣註冊response:

DI()->response = 'PhalApi_Response_Explorer';

1.14.5 擴展你的返回格式

當你的項目需要返回其他格式時,如返回XML,則可以先這樣實現你的格式類:

class MyResponse_XML extends PhalApi_Response {

    protected function formatResult($result) {
        //TODO:把數組$result格式化成XML ...
    }
}

隨後,也是簡單重新註冊一下即可:

DI()->response = 'MyResponse_XML';

1.14.6 各狀態碼產生的時機

各狀態碼產生的時機

1.14.7 更好地建議

很多時候,很多業務場景,客戶端在完成一個接口請求並獲取到所需要的數據後,需要進行不同的處理的。

  • 就登錄來說,當登錄失敗時,可能需要知道:
  • 是否用戶名不存在?
  • 是否密碼錯誤?
  • 是否已被系統屏蔽?
  • 是否密碼錯誤次數超過了最大的重試次數?
  • ...

顯然,這裏也有一個返回狀態碼,更準備來說,是業務操作狀態碼。並且,此類的狀態依接口不同而不同,很難做到統一。

SO?

我們建議的是,項目接口在業務數據data裏面統一再定義一個狀態碼,通常爲code字段,完整路徑即: data.code ,同時爲0時表示操作成功,非0時爲不同的失敗場景。如上面的登錄:

  • code = 0 登錄成功
  • code = 1 用戶名不存在
  • code = 2 密碼錯誤
  • code = 3 系統已屏蔽此賬號
  • code = 4 密碼錯誤次數超過了最大的重試次數
  • ...

最後,客戶端在獲取到接口返回的數據後,先統一判斷ret是否正常請求並正常返回,即ret = 200;若是,則再各自判斷操作狀態碼code是否爲0,如果不爲0,則提示相應的文案並進行相應的引導,如果爲0,則走正常流程!

1.14.8 領域特定設計與Fiat標準

在《RESTful Web APIs》一書中提及到,標準可以劃歸到4個分類,分別是:fiat標準、個人標準、公司標準以及開放標準。

顯然,我們這裏推薦的是 JSON + ret-data-msg 返回格式既不是個人標準,也不是公司標準(就筆者觀察的範籌而言,未發現某個公司定義了此格式)。而且,也不屬於開放標準,因爲也還沒達到此程度。更多的,它是fiat標準。
我們很容易發現,身邊的應用、系統以及周圍項目都在使用諸如此類的返回結構格式,如一些AJAX的接口。

當然,我們可希望可以消除語義上的鴻溝,以便在後臺接口開發上有一個很好地共識。

同時,JSON + ret-data-msg 返回格式也是一種領域特定的格式,它更多是爲app多端獲取業務數據而製作的規範。雖然它不是很完美,不具備自描述消息,也沒有資源鏈接的能力,但我們認爲它是一種恰到好處的格式。
在基於JSON通用格式的基礎上,加以 ret-data-msg 的約束,它很好地具備了統一性,可能門檻低,容易理解。

//接口請求格式
http://dev.phalapi.com/demo/?service=User.GetBaseInfo&user_id=帳號ID

//返回結果格式
{
    "ret": 200,
    "data": {           
        "code": 0,    //狀態碼,0表示正常獲取,1表示用戶不存在
        "msg": "",
        "info": {      //用戶信息
            "id": "1",    //用戶ID
            "name": "dogstar",   //帳號
            "note": "oschina"   //來源
        }
    },
    "msg": ""
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章