用JSON-server模擬REST API

本文原址:https://www.cnblogs.com/ys-wuhan/p/6387791.html

在此,非常感謝原作者的耐心整理!

在開發過程中,前後端不論是否分離,接口多半是滯後於頁面開發的。所以建立一個REST風格的API接口,給前端頁面提供虛擬的數據,是非常有必要的。

對比過多種mock工具後,我最終選擇了使用 json server 作爲工具,因爲它足夠簡單,寫少量數據,即可使用。
也因爲它足夠強大,支持CORS和JSONP跨域請求,支持GET, POST, PUT, PATCH 和 DELETE 方法,更提供了一系列的查詢方法,如limit,order等。下面我將詳細介紹 json server 的使用。

安裝

首先你的電腦中需要安裝nodejs,建議使用最新版本。然後全局安裝json server.

npm install json-server -g
使用linux和macOS的電腦需要加上sudo

sudo npm install json-server -g
安裝完成後可以用 json-server -h 命令檢查是否安裝成功,成功後會出現

json-server [options] <source>

選項:
--config, -c Path to config file [默認值: "json-server.json"]
--port, -p Set port [默認值: 3000]
--host, -H Set host [默認值: "0.0.0.0"]
--watch, -w Watch file(s) [布爾]
--routes, -r Path to routes file
--static, -s Set static files directory
--read-only, --ro Allow only GET requests [布爾]
--no-cors, --nc Disable Cross-Origin Resource Sharing [布爾]
--no-gzip, --ng Disable GZIP Content-Encoding [布爾]
--snapshots, -S Set snapshots directory [默認值: "."]
--delay, -d Add delay to responses (ms)
--id, -i Set database id property (e.g. _id) [默認值: "id"]
--quiet, -q Suppress log messages from output [布爾]
--help, -h 顯示幫助信息 [布爾]
--version, -v 顯示版本號 [布爾]

示例:
json-server db.json
json-server file.js
json-server http://example.com/db.json

https://github.com/typicode/json-server

運行

安裝完成後,可以在任一目錄下建立一個 xxx.json 文件,例如在 mock/ 文件夾下,建立一個 db.json 文件,並寫入以下內容,並在 mock/ 文件夾下執行 json-server db.json -p 3003 。

{
"news":[
{
"id": 1,
"title": "曹縣宣佈昨日晚間登日成功",
"date": "2016-08-12",
"likes": 55,
"views": 100086
},
{
"id": 2,
"title": "長江流域首次發現海豚",
"date": "2016-08-12",
"likes": 505,
"views": 9800
}
],
"comments":[
{
"id": 1,
"news_id": 1,
"data": [
{
"id": 1,
"content": "支持黨中央決定"
},
{
"id": 2,
"content": "抄寫黨章勢在必行!"
}
]
}
]
}
爲了方便,再創建一個 package.json 文件,寫入

{
"scripts": {
"mock": "json-server db.json --port 3003"
}
}
然後使用到 /mock 目錄下執行 npm run mock 命令,如果成功會出現

@ mock /你的電腦中mock文件夾所在目錄的路徑/mock
json-server db.json -p 3003

{^_^}/ hi!

Loading db.json
Done

Resources
http://localhost:3003/news
http://localhost:3003/comments

Home
http://localhost:3003
如果不成功請檢查 db.json 文件的格式是否正確。

操作數據

GET

這個時候訪問 http://localhost:3003/db 可以查看 db.json 文件中所定義的全部數據。
使用瀏覽器地址欄,jQuery.get 或 fecth({method: "get"}) 訪問 http://localhost:3003/news ,則可以看到 news 對象下的數據,以Array格式返回:

[
{
"id": 1,
"title": "曹縣宣佈昨日晚間登日成功",
"date": "2016-08-12",
"likes": 55,
"views": 100086
},
{
"id": 2,
"title": "長江流域首次發現海豚",
"date": "2016-08-12",
"likes": 505,
"views": 9800
}
]

POST

以jquery的 $.ajax 方法舉例,以下代碼會實時的向 db.json 中的 news 對象push一條新的數據再次用 get 方式訪問 http://localhost:3003/news , 就可以看到它了

$.ajax({
type: 'post',
url: 'http://localhost:3003/news',
data: {
"id": 3,
"title": "我是新加入的新聞",
"date": "2016-08-12",
"likes": 0,
"views": 0
}
}
)

PUT

同樣以jquery的 $.ajax 方法舉例,以下代碼會實時的對 db.json 中的 news 對象中 id=1 數據進行修改

$.ajax({
type: 'put',
url: 'http://localhost:3003/news/1',
data: {
"title": "曹縣宣佈昨日晚間登日失敗",
"date": "2016-08-12",
"likes": 55,
"views": 100086
}
}
)

// 結果

[
{
"id": 1,
"title": "曹縣宣佈昨日晚間登日失敗",
"date": "2016-08-12",
"likes": 55,
"views": 100086
}
]
PATCH 和 DELETE 使用方式同上,就不做演示了。


上一篇演示瞭如何安裝並運行 json server , 在這裏將使用第三方庫讓模擬的數據更加豐滿和實用。

使用動態數據

上一篇演示時,使用了 db.json 作爲數據載體,雖然方便,但是如果需要大量的數據,則顯得力不從心。
幸好 json server 可以通過js動態生成json格式數據,官方例子爲生成1000組user數據:

/mock/db.js

module.exports = function() {
var data = { users: [] }
// Create 1000 users
for (var i = 0; i < 1000; i++) {
data.users.push({ id: i, name: 'user' + i })
}
return data
}
/mock 下運行

json-server db.js -p 3003
我們訪問 http://localhost:3003/news/ 看到的數據是

[
{"id": 0,"name": "user0"},
{"id": 1,"name": "user1"},
{"id": 2,"name": "user2"},
{"id": 3,"name": "user3"},
...
{"id": 999,"name": "user999"}
]
但是在開發環境中,name 這個屬性應該是諸如 “李鐵蛋”, “張豔華” 或者是 “Brenda Thomas”,
“Daniel Wilson” 這樣接地氣的名字,而不是 “user0”, “user1” 這樣讓人望而生畏的名字,對於用戶的
年齡,性別,籍貫,也應該有比較合理的數據展示。

爲什麼選擇mockjs

數據生成器有很多,比較出名的有 faker ,chance ,mockjs 等,其中最爲強大的非 faker 莫屬,不但擁有幾乎全部常用的數據格式,而且還有中英德法等多種語言的數據。但是在實際測試中發現,faker 對中文數據的支持還是以西方文字爲基礎,並不能很好的模擬中文,例如:

let faker = require('faker');

faker.locale = "zh_CN";

console.log(faker.address.city()); => 南 羅
console.log(faker.address.streetName()); => 陳 橋
console.log(faker.company.companyName()); => 靜琪 - 越澤
console.log(faker.date.month()); => May
console.log(faker.internet.email()); => [email protected]
console.log(faker.phone.phoneNumber()); => 922-61957652
這些看起來有些怪異的中文格式,多半是不能用於國內的數據模擬的,我們再看看 mockjs 的表現:

let Mock = require('mockjs');
let Random = Mock.Random;

console.log(Random.city()); => 珠海市
console.log(Random.cname()); => 韓桂英
console.log(Random.date()); => 2007-08-05
console.log(Mock.mock({ => {stars: '★★★★★'}
"stars|1-10": "★"
}));
Random.image('200x100', '#4A7BF7', 'hello')
=> 見下圖

雖然 mockj s可以模擬的數據不如 faker 那麼多,但是由於其對中文的良好支持,並且使用了位於國內的隨機圖片提供商,顯然是更適合國情的選擇。

mockjs用法示例
請先用15分鐘閱讀 mockjs官方文檔

安裝mockjs

在 /mock 目錄下安裝

npm install mockjs --save
Mock.mock
我知道有些人不會去認真的閱讀官方文檔,所以在此摘抄一些官方文檔中的例子作爲示範:

// repeat 方法(部分)

Mock.mock({
"string|5": "★" => "string": "★★★★★"
"string|1-10": "★" => "string": "★★"
"number|1-100": 100 => "number": 85
"number|1-100.2": 100 => "number": 25.69
})

Mock.Random
我知道有些人不會去認真的閱讀官方文檔,所以在此摘抄一些官方文檔中的例子作爲示範:

// random 方法(部分)

Random.integer(60, 100) => 78
Random.float(60, 100) => 89.565475
Random.range(60, 100) => [60,61,62,...,99]
Random.date() => "2018-12-28"
Random.image('200x100','#396') => "http://dummyimage.com/200x100/396"
Random.color() => "#79d8f2" (默認使用hex顏色)
Random.county(true) => "浙江省 舟山市 岱山縣"
爲什麼不在瀏覽器中使用mockjs
通過閱讀 mockjs 的官方文檔可以發現,它其實是作爲一個獨立的 mock server 存在的,就算沒有json server,一樣可以反饋數據,但是由於以下一些缺點,讓我只能把它作爲一個數據構造器來使用:

不能跨域使用

與某些框架中的路由處理邏輯衝突

無法定義複雜的數據結構,比如下面的數據結構,images 將會是字符串 [object object], 而非預想中的數組:

Mock.mock({
"list|1-10": [
"id|+1": 1,
"images": [1,2,3]
]
})
無法自定義較爲複雜的路由

示例

下面是一個使用 mockjs 構造的比較複雜的數據格式,對象是一個新聞列表,其中有100條新聞,每條新聞有對應的id,標題,內容,簡介,標籤,瀏覽量,和一個圖片數組:

/mock/db.js

let Mock = require('mockjs');
let Random = Mock.Random;

module.exports = function() {
var data = {
news: []
};

var images = [1,2,3].map(x=>Random.image('200x100', Random.color(), Random.word(2,6)));

for (var i = 0; i < 100; i++) {

var content = Random.cparagraph(0,10);

data.news.push({
     id: i, 
     title: Random.cword(8,20),
     desc: content.substr(0,40),
     tag: Random.cword(2,6),
     views: Random.integer(100,5000),
     images: images.slice(0,Random.integer(1,3))
})

}

return data
}

/mock 下運行

json-server db.js -p 3003
訪問 http://localhost:3003/news 看到的數據是:

[
{
"id": 0,
"title": "元小總小把清保住影辦歷戰資和總由",
"desc": "共先定製向向圓適者定書她規置鬥平相。要廣確但教金更前三響角面等以白。眼查何參提適",
"tag": "值集空",
"views": 3810,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置",
"http://dummyimage.com/200x100/f28279&text=收面幾容受取",
"http://dummyimage.com/200x100/7993f2&text=做件"
]
},
{
"id": 1,
"title": "物器許條對越復術",
"desc": "方江周是府整頭書生權部部條。始克識史但給又約同段十子按者感律備。關長廠平難山從合",
"tag": "分七眼術保",
"views": 4673,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置"
]
},
{
"id": 2,
"title": "但學卻連質法計性想般最",
"desc": "以羣親它天即資幾行位具回同務度。場養驗快但部光天火金時內我。任提教毛辦結論感看還",
"tag": "響六",
"views": 4131,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置",
"http://dummyimage.com/200x100/f28279&text=收面幾容受取",
"http://dummyimage.com/200x100/7993f2&text=做件"
]
},
...
{
"id": 99,
"title": "則羣起然線部其深我位價業紅候院",
"desc": "爲高值務須西生型住斷況裏聽。志置開用她你然始查她響元還。照員給門次府此據它後支越",
"tag": "何你",
"views": 2952,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置"
]
}
]

前面演示瞭如何安裝並運行 json server , 和使用第三方庫真實化模擬數據 , 下面將展開更多的配置項和數據操作。

配置項

在安裝好json server之後,通過 json-server -h 可以看到如下配置項:

json-server [options] <source>

Options:
--config, -c 指定 config 文件 [默認: "json-server.json"]
--port, -p 設置端口號 [default: 3000]
--host, -H 設置主機 [默認: "0.0.0.0"]
--watch, -w 監控文件 [boolean]
--routes, -r 指定路由文件
--static, -s 設置靜態文件
--read-only, --ro 只允許 GET 請求 [boolean]
--no-cors, --nc 禁止跨域資源共享 [boolean]
--no-gzip, --ng 禁止GZIP [boolean]
--snapshots, -S 設置快照目錄 [默認: "."]
--delay, -d 設置反饋延時 (ms)
--id, -i 設置數據的id屬性 (e.g. _id) [默認: "id"]
--quiet, -q 不輸出日誌信息 [boolean]
--help, -h 顯示幫助信息 [boolean]
--version, -v 顯示版本號 [boolean]

Examples:
bin db.json
bin file.js
bin http://example.com/db.json
既可以通過命令行方式單行配置,如

json-server db.js -p 3003 -d 500 -q -r ./routes.json
,也可以通過 json-server.json 文件進行配置後:

/mock/json-server.json

{
"host": "0.0.0.0",
"port": "3003",
"watch": false,
"delay": 500,
"quiet": true,
"routes": "./routes.json"
}

運行

json-server db.js
返回靜態文件
在 /mock 下建立 public 目錄,即可直接訪問其下的所有靜態文件,包括但不限於
js, css ,markdown 文件等。

地址欄輸入 http://localhist:3003/readme.md 即可訪問以下文件

/mock/public/readme.md

移動設備訪問

通過 json server 建立的rest api服務默認可以在局域網中通過WIFI訪問接口。
windows下面通過 ipconfig 查找到電腦的局域網地址.mac設備是通過 ifconfig | grep "inet " | grep -v 127.0.0.1 查看。
比如我的電腦局域網ip是 192.168.0.6,在手機上訪問 http://192.168.0.6:3003 即可。

自定義路由

可以通過自定義路由的形式,簡化數據結構,或是建立高彈性的web api,例如

/mock/routes.json

{
"/news/:id/show": "/news/:id",
"/topics/:id/show": "/news/:id",

}
訪問 /news/1/show 和 topics/1/show 均返回指定的 /news/1 內容。

  • 需要注意的是,路由必須以 / 開頭

npm啓動

相比在終端中直接輸入各種命令,我更喜歡利用 node scripts 來處理任務,在 /mock 下建立文件 package.json,然後運行 npm run mock 。

/mock/package.json

{
"scripts": {
"mock": "json-server db.js"
}
}

數據過濾

數據過濾是 json server 中非常強力的功能。通過url上簡單的query字段,即可過濾出各種各樣的數據。
示例數據源:

[
{
"id": 0,
"title": "元小總小把清保住影辦歷戰資和總由",
"desc": "共先定製向向圓適者定書她規置鬥平相。要廣確但教金更前三響角面等以白。眼查何參提適",
"tag": "值集空",
"views": 3810,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置",
"http://dummyimage.com/200x100/f28279&text=收面幾容受取",
"http://dummyimage.com/200x100/7993f2&text=做件"
]
},
{
"id": 1,
"title": "物器許條對越復術",
"desc": "方江周是府整頭書生權部部條。始克識史但給又約同段十子按者感律備。關長廠平難山從合",
"tag": "分七眼術保",
"views": 4673,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置"
]
},
{
"id": 2,
"title": "但學卻連質法計性想般最",
"desc": "以羣親它天即資幾行位具回同務度。場養驗快但部光天火金時內我。任提教毛辦結論感看還",
"tag": "響六",
"views": 4131,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置",
"http://dummyimage.com/200x100/f28279&text=收面幾容受取",
"http://dummyimage.com/200x100/7993f2&text=做件"
]
},
...
{
"id": 99,
"title": "則羣起然線部其深我位價業紅候院",
"desc": "爲高值務須西生型住斷況裏聽。志置開用她你然始查她響元還。照員給門次府此據它後支越",
"tag": "何你",
"views": 2952,
"images": [
"http://dummyimage.com/200x100/79f2a5&text=別角置"
]
}
]

屬性值(Filter)

使用 . 操作對象屬性值

// 獲取圖片數量爲3,且標籤字數爲2的新聞

GET /news?images.length=3&tag.length=2
分割(Slice)
使用 _start 和 _end 或者 _limit (response中會包含 X-Total-Count)

// 獲取id=10開始的5篇新聞

GET /news?_start=10&_limit=5

// 獲取id=20開始,id=35結束的新聞

GET /news?_start=20&_end=35
排序(Sort)
使用 _sort 和 _order (默認使用升序(ASC))

// 按照瀏覽數量降序排列

GET /news?_sort=views&_order=DESC
運算符(Operators)
使用 _gte 或 _lte 選取一個範圍

// 選取瀏覽量在2000-2500之間的新聞

GET /news?views_gte=2000&views_lte=2500
使用 _ne 排除一個值

// 選擇tag屬性不是 "國際新聞" 的分類

GET /news?tag_ne=國際新聞
使用 _like 進行模糊查找 (支持正則表達式)

// 查找title中含有 "前端" 字樣的新聞

GET /news?title_like=前端
全文檢索(Full-text search)
使用 q,在對象全部value中遍歷查找包含指定值的數據

// 查找新聞全部字段包含 "強拆" 字樣的數據

GET /news?q=強拆
關係圖譜(Relationships)
獲取包含下級資源的數據, 使用 _embed

GET /news?_embed=comments
GET /news/1?_embed=comments
獲取包含上級資源的數據, 使用 _expand

GET /news?_expand=post
GET /news/1?_expand=post

作爲中間件

除了獨立作爲rest api 服務器之外, json server 同樣可以作爲諸如 Express 之類框架的中間件使用,具體API詳見 json server模塊

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