内容简介:新建db.json用于测试
#Linxu/Mac os sudo npm install json-server -g #window npm install json-server -g 复制代码
新建db.json用于测试 json-server db.json -p 3003
,-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": "抄写党章势在必行!" } ] } ] } 复制代码
出现错误:
/usr/bin/env: node: No such file or directory
解决
ln -s /usr/bin/nodejs /usr/bin/node 复制代码
json-server requires at least version 6 of Node, please upgrade
解决
sudo npm cache clean -f sudo npm install -g n sudo n stable 复制代码
快速启动脚本
db.json 目录下新建 package.json
, 运行 npm run mock
{ "scripts": { "mock": "json-server db.json --port 3003" } } 复制代码
简单的数据操作
- json-server和postman 简单教程 postman是模拟请求的开发神器
-
POST, PUT, PATCH or DELETE 这些操作会自动的保存在db.json文件里,请求必须是Json格式,包含头文件
Content-Type: application/json
否则返回的虽然是200 OK,但是不会修改数据
GET
http://localhost:3003/db ==> db.json
http://localhost:3003/news ==> news节点
POST
Postman向 http://localhost:3003/news
传参数
"id": 3, "title": "我是新加入的新闻", "date": "2016-08-12", "likes": 0, "views": 0 复制代码
json-server 后台反应
POST /news?id=3&title=%E6%88%91%E6%98%AF%E6%96%B0%E5%8A%A0%E5%85%A5%E7%9A%84%E6%96%B0%E9%97%BB&date=2016-08-12&likes=0&views=0 201 2.622 ms - 13 复制代码
使用url encode 解码点击UrlDecode解码
POST /news?id=3&title=我是新加入的新闻&date=2016-08-12&likes=0&views=0 201 2.622 ms - 13 复制代码
PUT
json-server 后台打印
PUT /news?title=我是新加入的新闻&date=2016-08-12&likes=55&views=100086 404 2.430 ms - 2 复制代码
模拟动态数据
简单的返回数组
/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 } 复制代码
运行
json-server db.js -p 3003 复制代码
访问
http://localhost:3003/users 复制代码
返回
[ { "id": 0, "name": "user0" }, { "id": 1, "name": "user1" } ...... ] 复制代码
拒绝僵硬的数据,引入mockjs
安装mockjs 在 /mock
目录下安装
npm install mockjs --save 复制代码
示例:返回100条新闻数据
// # /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 } 复制代码
运行
json-server db.js -p 3000 复制代码
访问 http://localhost:3000/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=做件" ] }, ...... ] 复制代码
Mock 语法
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.boolean() => true false 各50% 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) => "浙江省 舟山市 岱山县" 复制代码
- Rnadom.image
Random.image() // => "http://dummyimage.com/125x125" Random.image('200x100') // => "http://dummyimage.com/200x100" Random.image('200x100', '#fb0a2a') // => "http://dummyimage.com/200x100/fb0a2a" Random.image('200x100', '#02adea', 'Hello') // => "http://dummyimage.com/200x100/02adea&text=Hello" Random.image('200x100', '#00405d', '#FFF', 'Mock.js') // => "http://dummyimage.com/200x100/00405d/FFF&text=Mock.js" Random.image('200x100', '#ffcc33', '#FFF', 'png', '!') // => "http://dummyimage.com/200x100/ffcc33/FFF.png&text=!" 复制代码
- Text
paragraph-> centence -> word -> title #中文 Random.cparagraph() Random.cparagraph( len ) Random.cparagraph( min, max ) #随机生成一段中文文本 Random.csentence() Random.csentence( len ) Random.csentence( min, max ) # 随机生成一个汉字 Random.cword() Random.cword( pool ) Random.cword( length ) Random.cword( pool, length ) Random.cword( min, max ) Random.cword( pool, min, max ) 复制代码
进阶
加工数据
Filter
对应的数据九宫格
comments:[ { "id": 1, "news_id": 1, "author":{ "name":"a1", "age":32 }, "data": [ { "id": 1, "content": "支持党中央决定" }, { "id": 2, "content": "抄写党章势在必行!" } ] } ] 复制代码
查询语句:
GET /comments?id=1r&new_id=2 GET /comments?author.name=a1 复制代码
Paginate 分页
GET /posts?_page=7 GET /posts?_page=7&_limit=20 复制代码
- 默认返回 10 items
- 表头会出现 first, prev, next and last 的直接访问地址,x-total-count数据总数信息
access-control-expose-headers →X-Total-Count, Link link →<http://localhost:3000/news?_page=1>; rel="first", <http://localhost:3000/news?_page=2>; rel="next", <http://localhost:3000/news?_page=2>; rel="last" x-total-count →20 复制代码
关系图谱
posts id 和comments id 是关联的
{ "posts": [ { "id": 1, "title": "post的第一个title", "author": "typicode" }, { "id": 2, "title": "post的第二个title", "author": "tangcaiye" } ], "comments": [ { "id": 1, "body": "some comment1111", "postId": 2 }, { "id": 2, "body": "some comment2222", "postId": 1 } ], "profile": { "name": "typicode" } } 复制代码
-
_embed
http://localhost:3000/posts/2?_embed=comments
返回posts/2
下级关联数据comments
{ "id": 2, "title": "post的第二个title", "author": "tangcaiye", "comments": [ { "id": 1, "body": "some comment1111", "postId": 2 } ] } 复制代码
-
_expand
http://localhost:3000/comments/2?_expand=post
返回comments上级关联数据post
{ "id": 2, "body": "some comment2222", "postId": 1, "post": { "id": 1, "title": "post的第一个title", "author": "typicode" } } 复制代码
其他
排序
默认升序
GET /posts?_sort=views&_order=asc GET /posts/1/comments?_sort=votes&_order=asc 复制代码
切片 Slice
包括_star,不包括_end
GET /posts/1/comments?_start=20&_end=30 GET /posts/1/comments?_start=20&_limit=10 复制代码
汇总
# _gte > || _lte < GET /posts?views_gte=10&views_lte=20 # _ne != GET /posts?id_ne=1 # _like 注意title的字段名称 GET /posts?title_like=server # 全局搜索 GET /posts?q=internet # 直接获取数据 GET /db 复制代码
路由设置
注意:没有设置路由(主要是: "host": "0.0.0.0" 属性)之前 json-server --watch db.json
只有本机能访问,也就是局域网外网都不能访问
- 可以用-H 命令指定
json-server --watch db.json -H 0.0.0.0 复制代码
-
host 设置为
127.0.0.1
或者本地局域网IP地址 如192.168.1.168
无效 ,(服务器指定127.0.0.1/ 192.168.1.168是本地调试模式)具体解释网址 大意: 0.0.0.0指的是本机上的所有IPV4地址
IPV4中,0.0.0.0地址被用于表示一个无效的,未知的或者不可用的目标。* 在服务器中,0.0.0.0指的是本机上的所有IPV4地址,如果一个主机有两个IP地址,192.168.1.1 和 10.1.2.1,并且该主机上的一个服务监听的地址是0.0.0.0,那么通过两个ip地址都能够访问该服务。 * 在路由中,0.0.0.0表示的是默认路由,即当路由表中没有找到完全匹配的路由的时候所对应的路由。
设置的两种方法
- 直接命令行指定路由文件
json-server db.js -p 3003 -d 500 -q -r ./routes.json 复制代码
-
json-server.json
文件进行配置后,直接json-server db.json
# /mock/json-server.json { "host": "0.0.0.0", "port": "3003", "watch": false, "delay": 500, "quiet": true, "routes": "./routes.json" } 复制代码
自定义路由,可以指定访问链接返回指定的数据,而且可以动态修改
routes.json
{ "/api/*": "/$1", "/:resource/:id/show": "/:resource/:id", "/posts/:category": "/posts?category=:category", "/articles\\?id=:id": "/posts/:id" } 复制代码
对应的效果
/api/posts # → /posts /api/posts/1 # → /posts/1 /posts/1/show # → /posts/1 /posts/javascript # → /posts?category=javascript /articles?id=1 # → /posts/1 复制代码
"/api/*": "/$1" /:resource /
增加中间件
// hello.js module.exports = (req, res, next) => { res.header('X-Hello', 'World') next() } json-server db.json --middlewares ./hello.js json-server db.json --middlewares ./first.js ./second.js 复制代码
Nodejs Module 不用等后台同事API
为什么学了上面还要学nodejs的案例呢? 因为上面的技能还不能很好的满足开发中REST API的需求
- rount.json 储存在文件中修改比较麻烦
- 只用配置文件,不很好使用Mock的相关功能
- 把配置放在js中相对灵活,能动态的拦截返回和处理相关逻辑
最简单案例
node 安装 json-server模块
$ npm install json-server --save-dev 复制代码
// server.js const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') //默认为当前目录 //const path = require('path') 指定其他目录 //const router = jsonServer.router(path.join(__dirname, 'db.json')) const middlewares = jsonServer.defaults() server.use(middlewares) server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) // 运行 $ node server.js 复制代码
自定义路由
const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') const middlewares = jsonServer.defaults() // Set default middlewares (logger, static, cors and no-cache) server.use(middlewares) // Add custom routes before JSON Server router server.get('/echo', (req, res) => { res.jsonp(req.query) }) // To handle POST, PUT and PATCH you need to use a body-parser // You can use the one used by JSON Server server.use(jsonServer.bodyParser) server.use((req, res, next) => { if (req.method === 'POST') { req.body.createdAt = Date.now() } // Continue to JSON Server router next() }) // Use default router server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) 复制代码
对上面的几点进行说明
res.jsonp res ==> respose
res.status(500).jsonp({ error: "error message here" "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900 }) 复制代码
请求的返回Json格式
{ "error": "error message here" "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900 } 复制代码
req.body.createdAt = Date.now() 往返回的jons中插入createAt字段,如本应返回
{ "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900 } 复制代码
加入req.body.createdAt = Date.now()后返回
{ "id": 21, "title": "长江", "date": "2016-09-12", "likes": 509, "views": 9900, "createdAt": 1536476508883, } 复制代码
js 增加router.json 配置
// Add this before server.use(router) server.use(jsonServer.rewriter({ '/api/*': '/$1', '/blog/:resource/:id/show': '/:resource/:id' })) 复制代码
访问控制
const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') const middlewares = jsonServer.defaults() server.use(middlewares) server.use((req, res, next) => { if (isAuthorized(req)) { // add your authorization logic here next() // continue to JSON Server router } else { res.sendStatus(401) } }) server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) 复制代码
自定义输出
// In this example, returned resources will be wrapped in a body property router.render = (req, res) => { res.jsonp({ body: res.locals.data }) //res.jsonp => 包裹数据成json格式 //res.send => 直接发送字符串 } 复制代码
访问本应返回
{ "id": 21, "title": "长江", "date": "2016-09-12" } 复制代码
增加 body: res.locals.data后返回
{ body: { id: 1, title: "曹县宣布昨日晚间登日成功", date: "2016-08-12", likes: 55, views: 100086 } } 复制代码
终极Demo
访问 http://localhost:3000/echo
返回模拟数据
const jsonServer = require('json-server') const server = jsonServer.create() const router = jsonServer.router('db.json') const middlewares = jsonServer.defaults() let Mock = require('mockjs'); server.use(middlewares) var template = { 'titles': 'Syntax Demo', 'string1|1-10': '★', 'string2|3': 'value', 'number1|+1': 100, 'number2|1-100': 100, 'number3|1-100.1-10': 1, 'number4|123.1-10': 1, 'number5|123.3': 1, 'number6|123.10': 1.123, 'boolean1|1': true, 'boolean2|1-2': true, 'object1|2-4': { '110000': '北京市', '120000': '天津市', '130000': '河北省', '140000': '山西省' }, 'object2|2': { '310000': '上海市', '320000': '江苏省', '330000': '浙江省', '340000': '安徽省' }, 'array1|1': ['AMD', 'CMD', 'KMD', 'UMD'], 'array2|1-10': ['Mock.js'], 'array3|3': ['Mock.js'], 'function': function() { return this.titles } } server.get('/echo', (req, res) => { var data = Mock.mock(template) var json = JSON.stringify(data, null, 4) console.log('-----------------\n' + json) res.send(json) }) // To handle POST, PUT and PATCH you need to use a body-parser // You can use the one used by JSON Server server.use(jsonServer.bodyParser) server.use((req, res, next) => { console.log('--------------'+req.method) if (req.method === 'POST') { req.body.createdAt = Date.now() req.body.test = 1 } // Continue to JSON Server router next() }) // 返回错误码,和指定json格式的数据 //router.render = (req, res) => { // res.status(500).jsonp({ // error: "error message here" // "id": 21, // "title": "长江", // "date": "2016-09-12", // "likes": 509, // "views": 9900 // }) //} // Add this before server.use(router) server.use(jsonServer.rewriter({ '/api/*': '/$1', '/blog/:resource/:id/show': '/:resource/:id' })) router.render = (req, res) => { res.jsonp({ body: res.locals.data }) } server.use(router) server.listen(3000, () => { console.log('JSON Server is running') }) 复制代码
附录
json-server 命令参数
json-server index.js [options] <source> 选项: --config, -c Path to config file [默认值: "json-server.json"] --port, -p Set port [默认值: 3000] --host, -H Set host [默认值: "localhost"] --watch, -w Watch file(s) [布尔] --routes, -r Path to routes file --middlewares, -m Paths to middleware files [数组] --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"] --foreignKeySuffix, --fks Set foreign key suffix (e.g. _id as in post_id) [默认值: "Id"] --quiet, -q Suppress log messages from output [布尔] --help, -h 显示帮助信息 [布尔] --version, -v 显示版本号 [布尔] 示例: index.js db.json index.js file.js index.js http://example.com/db.json https://github.com/typicode/json-server Missing <source> argument 复制代码
以上所述就是小编给大家介绍的《自建-模拟JSON REST API-从入门到精通-前端必备技能-你还在等你后台API吗?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- [ Laravel从入门到精通 ] 测试系列 —— 通过测试驱动开发构建待办任务项目(二):前端功能和浏览器...
- 圣思园《精通Spring Boot/Cloud》与《精通Java并发》课程现已宣布
- Charles 从入门到精通
- MAT 入门到精通(一)
- Git 从入门到精通
- Webpack入门到精通(1)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML Dog
Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99
For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!