使用 JSON Server 构建数据接口
目前来说,前后端分离 是web开发的主流模式。前端负责页面制作、交互实现,后端负责数据API的开发。两者并行处理,各司其职,项目开发完毕后一起联调,出了问题也能快速定位。
而通常情况下,后端真实数据的研发往往滞后于UI界面的开发。所以,在项目开始前,前后端会约定好数据格式,这样,前端就可以先利用mock数据进行界面开发。一般的做法,是在本地新建多个json文件,然后利用ajax请求相应的文件,待后端数据接口开发完毕,直接将json地址换成真实接口地址即可。
但还是会有如下问题:
- 本地要建多个json数据文件
- 为接近真实场景,要生成多条数据,还要随机模拟内容
- 无法处理分页请求
- 除 GET,POST、PUT、PATCH、DELETE等请求,无法直接在浏览器操作
- …
为解决上述问题,你需要一个数据服务器,它就是 JSON Server。
一、安装与启动
JSON Server 是一个快速构建测试数据的 REST API 服务器。通过它,我们可以在短时间内创建多组测试数据,它允许我们自定义请求数据的路由,支持 GET,POST、PUT、PATCH、DELETE 等多种请求。另外,我们还可以跨域访问 JSON Server 构建的数据API。
安装
通过如下命令安装:
> npm install -g json-server |
我使用这款工具时,它的最新版本是 0.10.1
。安装完,我们可以通过以下命令,来查看相关信息:
> json-server -h |
CLI 输出的信息:

其中包括配置文件、端口、主机、监听文件、路由设置、中间件,静态文件、数据只读等设置,在右边可以看到它们的默认值。
启动
要启动 JSON Server 数据服务,首先,得创建一个数据文件。我们在任意位置新建一个文件夹 json-server
,进入该目录,再新建一个 db.json
数据文件 :
mkdir json-server && cd json-server |
打开 db.json
,加入内容:
{ |
接着,通过命令将数据文件与服务关联,可通过以下命令启动服务(db.json
里的内容一定要符合 JSON 格式,否者服务器会报错。):
> json-server --watch db.json |
将看到:

此时,打开 http://localhost:3000, 便能看到一个关于本地 JSON Server 的首页,里面包含的 Resources
项,便是我们创建的接口。
Resources |
/db
是总的数据接口,/posts
、/comments
分别是子接口,直接打开可访问到相应的数据。
这个 JSON Server 首页,我们也可以自定义。只需要在根目录下创建 ./public
文件夹,并在里面新建一个 index.html
页面即可。
二、数据操作
前面说到,JSON Server 支持多种请求方式,并支持跨域请求。我们可以在其他项目中去请求上面的数据服务,来看下它们对应的数据操作,这里假设你使用的是 Jquery,版本2.1.3:
请求方式
GET
GET 请求用于读取数据,以下内容通过不同参数请求不同接口:
var root = 'http://localhost:3000'; |
除了基本查询,JSON Server 还支持多条件组合查询,详见 条件查询
章节。
POST
POST 请求一般用于新增内容,以下为新增一篇文章:
var root = 'http://localhost:3000'; |
注意,对于一些版本的 jquery,需要在请求头添加 Content-Type: application/json
,否者 POST,PUT,PATCH 请求会被处理成 GET,不会对数据做任何改变 。
POST 请求发送完,ajax 回调函数将返回 db.json
存储的数据项。此时,打开 db.json
文件,你会发现数据项已经被写入到 db.json
中。
可以看到,倘若没有指定数据的 id 属性,则 JSON Server 会根据已有数据最大的 id 值进行自增。
倘若你 POST 的数据项里已经指定 id 的值,则存储到 db.json
里的字段值会变成字符串,比如你发送的数据为:
{id: 4, title: 'title four', body: 'post gh', flag: true} |
则存储数据为:
{"id": "4", "title": "title four", "body": "post gh", "flag": "true"} |
可以看到,id 和 flag 的值都被转换为字符串。
另外,对于提交相同 id 的数据,服务端会提示报错: Error: Insert failed; duplicate id.
。
DELETE
DELETE 请求一般用于删除内容,以下为删除 id 为 4 的文章:
var root = 'http://localhost:3000'; |
上面的 DELETE 请求返回一个空数组,表示删除成功。打开 db.json
文件,可以看到,第4篇文章已经被删除。
PUT
PUT 请求可更新或新增一项数据。它的具体作用是,当请求的数据存在,则更新该数据。当请求的数据不存在,则新增一项数据。以下分别为更新 id 为 1 的文章:
var root = 'http://localhost:3000'; |
但我尝试使用 PUT 发送新数据时,却出现 404 报错的情况。
PATCH
PATCH 请求是对 PUT 的补充,用于数据项的局部更新,以下为更新 id 为 2 的 body 属性值:
var root = 'http://localhost:3000'; |
对 JSON Server 数据服务发送 增删改查 的请求,它里面的数据会作相应的更新,这种更新是基于 lowdb 。
条件查询
JSON Server 提供了多种形式的条件查询,首先,在 db.json
里弄点数据,5篇文章、3条评论:
{ |
然后,再来看看每个查询操作:
过滤(Filter)
除了普通参数,还可通过 .
来访问深层属性:
- http://localhost:3000/posts?id=1&id=2
获取 posts 中 id 为 1 或 2 的 文章(db.json
中 posts 的第1和第2条) - http://localhost:3000/posts?author.name=lucy
获取 posts 中 author 属性 name 值为 lucy 的文章(db.json
中 posts 的第3、4条) - http://localhost:3000/posts?author.name=lucy&title=cc
获取 posts 中 author 属性 name 值为 lucy,且 title 为 cc 的文章(db.json
中 posts 的第3条) - http://localhost:3000/posts?tag.length=3
获取 posts 中 tag 个数为3的文章 (db.json
中 posts 的第3条)
相同参数(id)取或,不同参数(author.name、title)取与。
分页(Paginate)
可使用参数 _page
和 _limit
(可选),来返回分页数据。不用 _limit
时,默认返回 10 条。
- http://localhost:3000/posts?_page=1
获取 posts 中 前10条数据。若已有数据小于10条,则全部返回(db.json
中 posts 的全部数据) - http://localhost:3000/posts?_page=2&_limit=2
每页限制2条,获取 posts 中第二页数据 (db.json
中 posts 的第3、4条)
截取(Slice)
Slice 截取的规则和数组中的 slice 方法相同。可使用参数 _start
、_end
以及 _limit
,来返回截取数据。
- http://localhost:3000/posts?_start=1&_end=3
获取 posts 中第2条到第3条的数据(db.json
中 posts 的第2、3条) - http://localhost:3000/posts?_start=2&_end=4
获取 posts 中第3条到第4条的数据(db.json
中 posts 的第3、4条) - http://localhost:3000/posts?_start=2&_limit=2
从第二条开始,获取 posts 中 后2条数据(db.json
中 posts 的第3、4条)
包括 _start
的文章,但不包括 _end
的文章。可以把 _start
和 _end
看成数组项的索引值。
分类排序(Sort)
可使用参数 _sort
和 _order
,来返回排序的数据。
- http://localhost:3000/posts?_sort=likes&_order=asc
获取 posts 中按 likes 数升序的数据(db.json
中 posts 的 id 排序依次为 4、5、2、1、3) - http://localhost:3000/posts?_sort=likes&_order=desc
获取 posts 中按 likes 数降序的数据(db.json
中 posts 的 id 排序依次为 3、1、2、5、4)
运算(Operators)
可使用参数 _gte
和 _lte
,来返回一个范围的数据。
- http://localhost:3000/posts?likes_gte=100&likes_lte=1000
获取 posts 中 likes 数大于等于100、且小于等于1000的数据(db.json
中 posts 的第1、2、5条)
可使用参数 _ne
,来返回除指定之外的数据。
- http://localhost:3000/posts?author.name_ne=lucy
获取 posts 中除 author.name 为 lucy 的数据(db.json
中 posts 的第1、2、5条)
全文搜索(Full-text search)
可使用参数 q
,来返回包含指定字符的数据。它会匹配每项数据的所有字段。
- http://localhost:3000/posts?q=ttt
获取 posts 中字段值包含 ttt 的数据(db.json
中 posts 的第2条)
关联(Relationships)
可使用参数 _embed
,将关联子数据拼接起来。
- http://localhost:3000/posts/1?_embed=comments
获取 posts 中 id 为 1 的数据,并将它对应的 comments 数据拼接起来
返回数据为:
{ |
- http://localhost:3000/comments/1?_expand=post
获取 comments 中 id 为 1 的数据,并将它对应的 post 数据拼接起来
返回的数据为:
{ |
如果你觉得自己建立一个数据服务器,创建数据这些操作麻烦。希望可以直接调用数据,那也是没问题的,只需要通过 JSONPlaceholder。
三、JSONPlaceholder
JSONPlaceholder 可以说是 JSON Server 的一个线上例子,它是由 JSON Server 的作者开发的,正如它所建立的初衷:
Most of the time when trying a new library, hacking a prototype or following a tutorial, I found myself in need of some data.
I didn’t like the idea of using some public API because I had the feeling that I was spending more time registering a client and understanding a complex API than focusing on my task.
But I liked the idea of image placeholders for web designers. So I decided to code a little Express server inspired by that and here is JSONPlaceholder.
作者在开发一些项目时,需要若干测试数据。但网上一些公用的数据接口,需要注册,还要花时间了解流程以及API的使用方法。可是他只想专注项目本身的开发,于是,它对照web设计师所使用的 image placeholder,再结合 JSON Server,创建了 JSONPlaceholder。
基于大多数项目的常见需求,它提供了一套可用的API数据,用户直接调用即可。并且它有如下特点:
- 免注册
- 零设置(编码)
- API简单
- 关联性强
- 资源过滤和嵌套
- 跨域(CORS and JSONP)
- 支持 GET, POST, PUT, PATCH, DELETE 和 OPTIONS 请求
- 与 Backbone, AngularJS, Ember 等库兼容
它包含的数据API有:
接口 | 数据条数 |
---|---|
/posts | 100 |
/comments | 500 |
/albums | 100 |
/photos | 5000 |
/todos | 200 |
/users | 10 |
并且,你还能使用不同的请求方式去请求不同的路由:
请求方式 | 接口 | 描述 |
---|---|---|
GET | /posts | 获取所有文章 |
GET | /posts/1 | 获取第一篇文章 |
GET | /posts/1/comments | 通过 posts,查询第一篇文章所有的评论 |
GET | /comments?postId=1 | 通过 comments,查询第一篇文章所有的评论 |
GET | /posts?userId=1 | 获取 userId=1 发布的文章 |
POST | /posts | 新增一片文章 |
PUT | /posts/1 | 更新第一篇文章,没有相应的文章,则创建它 |
PATCH | /posts/1 | 更新第一篇文章的某个属性 |
DELETE | /posts/1 | 删除第一篇文章 |
而你要做的,只需要通过如下方式调用它即可(假如你用的Jquery):
var root = 'http://jsonplaceholder.typicode.com'; |
更多用法可参见,使用实例。
注意,你向 http://jsonplaceholder.typicode.com
发送的新增、修改、删除 的请求并不会真的对 jsonplaceholder 服务器上的数据执行 新增、修改、删除 的操作,它只是做了一个模拟请求。因此,如果你希望接近真实的数据操作,还是得通过 JSON Server 去创建一个数据服务。
四、JSON Server 深入
除了上面说到的内容外,JSON Server 还有一些相对高级的特性:
命令行设置
自定义访问目录
默认情况下,服务器本地有一个 JSON Server 首页。在文章前面有提到,我们可以在根目录下新建 ./public
目录,然后,在里面新建一个 index.html
便可自定义这个首页,除了 index.html
这个页面,我们还可以在 ./public
中放 js、images等文件。
./public
是默认指定的文件名。
若你不想使用 ./public
这么一个文件名,你也可通过 --static
命令手动指定其他文件夹。比如,在根目录新建 ./demo
目录, 要把 ./demo
作为访问目录。只需如下命令:
> json-server --watch db.json --static demo |
由于 ./demo
被当做了服务器访问的目录,因此启动后,通过 http://localhost:3000
便能访问 ./demo
目录的内容。
设置端口号
默认情况下,JSON Server 服务器的端口号是 3000,我们也可以手动设置,如下:
> json-server --watch db.json --port 9999 |
这里将端口号设置为 9999,打开 ,便能访问到 JSON Server 首页。
整合命令
除了上面说到的两个命令,JSON Server 还提供了其他多个命令。为了避免在 CLI 中输入一串参数,我们可以在根目录新建 json-server.json
文件来覆盖默认设置:
// json-server.json |
此时,运行 json-server db.json
即可启动服务,并让上述设置生效。
创建动态数据
除了手动新建 db.json
作为数据文件,我们还可以通过运行js文件来生成动态数据。在根目录新建 data.js
文件,加入代码:
// data.js |
运行 json-server data.js
,访问 http://localhost:9999/users, 便能看到生成的数据(存在内存):
[ |
自定义路由
我们并非一定要按照 db.json
定义的数据结构来访问相应的接口,可通过在根目录创建一个 routes.json
文件来自定义访问路由:
// routes.json |
在 json-server.json
文件中新增路由指定:
// json-server.json |
运行 json-server db.json
重启服务,此时,访问左边的地址,等价于访问右边的:
新路由 | 旧路由 |
---|---|
http://localhost:9999/api/p | http://localhost:9999/posts |
http://localhost:9999/api/c | http://localhost:9999/comments |
http://localhost:9999/api/p?id=1 | http://localhost:9999/posts/1 |
中间件
为了让数据访问功能更强大、更灵活,JSON Server 提供了中间件,用户可在数据返回前,进行相关操作。比如,下面这段代码便是在数据返回前,进行相关验证:
// server.js |
新增 server.js
文件后,你只需要运行 node server.js
, 便可返回数据前进行相关验证。