自建-模拟JSON REST API-从入门到精通-前端必备技能-你还在等你后台API吗?

栏目: 编程工具 · 发布时间: 6年前

内容简介:新建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 只有本机能访问,也就是局域网外网都不能访问

  1. 可以用-H 命令指定
json-server --watch db.json -H 0.0.0.0
复制代码
  1. 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吗?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML Dog

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》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具