json-server全攻略

一、基本认知

一个在前端本地运行,可以存储json数据的server。


二、基本使用方式(两种)

1.全局使用

(1)安装

$ npm install -g json-server


(2)使用

【Step1】首先准备一个json文件,如:db.json。

内容形如(db.json):

{

    "data1": [{

        "id": "001",

        "name": "Sherry",

        "age": 24,

        "friends": [{

            "id": "100",

            "name": "friend1"

        }, {

            "id": "200",

            "name": "friend2"

        }]

    }, {

        "id": "002",

        "name": "Addy",

        "age": 26

    }],

    "data2": {

        "id": "003",

        "name": "Jack",

        "age": 25

    },

    "data3": [{

        "id": "004",

        "name": "Rebeca",

        "age": 27

    }]

}

【Step2】使用全局json-server命令,启动mock服务。这个mock服务,管理的数据,就是db.json。

$ json-server --watch --port 3001 db.json

输出类似以下内容,说明启动成功。

【Step3】使用json-server支持的功能,尝试进行数据访问

【举些栗子】(均为GET请求)

访问:http://localhost:3001/db

http://localhost:3001/db

访问:http://localhost:3001/data1    (注意:这里不需要加/db,即不需要访问/db/data1)


http://localhost:3001/data1

访问:http://localhost:3001/data1/001

http://localhost:3001/data1/001

访问:http://localhost:3001/data1/Sherry    (只能通过id过滤数据)

「注」

如果想根据其他属性进行过滤,采用:http://localhost:3001/data1?name=Sherry

这里,通过?传参过滤,得到的结果是一个数组。(id过滤,拿到的是一个对象)

即:拿到所有name=Sherry的项。即使结果只有一项,也会返回包含一个数据的数组。

http://localhost:3001/data1/Sherry

访问:http://localhost:3001/data1/100

           http://localhost:3001/data1/friends

           http://localhost:3001/data1/friends/100

         (只支持匹配第一层数据的id)

http://localhost:3001/data1/100

「注」(mark坑。请记住这里。)

这就造成了一个问题,如果需要用json-server模拟多层路由嵌套,无法通过db.json中数据的多层嵌套,达到模拟多层路由嵌套的目的。

换句话说,路由只能匹配到db.json这个json最外层的key值。也就是例子中的data1、data2、data3。

而里层的key值,都不会被路由匹配。

至于/data1/001这样的访问方式,相当于对/data1这个路由下的数据,进行一个过滤,类似于从列表页进入详情/编辑页。也就是说,/data1/001相当于在模拟/data1/:id这样的访问方式,访问的仍然是/data1这个接口。这和严格意义上的路由匹配,是不一样的。


访问:http://localhost:3001/data2

http://localhost:3001/data2

访问:http://localhost:3001/data2/003    

(只有数组数据,支持id过滤。进一步印证了,这种访问方式类似于列表页进入详情/编辑页)

http://localhost:3001/data2/003


(3)其他类型请求(POST, PUT, PATCH ,DELETE),json-server的行为。

【举些栗子】

POST访问:/data1    (返回数组的接口)

两次 POST /data1 — body未传值

行为:向/data1对应的数组添加新对象。

对象的属性取决于POST请求中body的设置。

如果body没有设置,json-server仍然会给/data1数组添加一个新对象,并赋予一个默认的id值,新对象有且仅有id这一个属性。

如果用户只设置了id以外的属性,json-server也会给新对象生成一个随机的id值。

POST/PUT/PATCH访问:/data2 (返回对象的接口:行为同访问/data1/001)

POST /data2

行为:修改/data2(或/data1/001)对应的对象属性。

「注」这里对象的id,不再是必需值。

DELETE访问:/data2 (返回的对象的接口)

行为:不进行删除。

DELETE访问:/data1/002 (请求删除数组列表的某一项)

行为:成功删除。


(4)自定义路由

可使用单独的route.json文件,进行自定义路由。(类似于代理转发,拦截请求,并重定向访问)

$ json-server --watch --routes route.json db.json

route.json形如:

{

    "/data/*": "/$1",      //    /data/data1  ==>  /data1

    "/:resource/:id/show": "/:resource/:id",    //    /data1/001/show ==> /data1/001

    "/data1/:name": "/data1?name=:name",    //    /data1/Sherry ==> /data1?name=Sherry

    "/:anyArray\\?id=:id": "/:anyArray/:id"                     //    /data1?id=002 ==> /data/002 

}


(5)自定义配置文件

配置文件默认为json-server.json。形如:

{

    "port": 3001,

    "watch": true,

    "static": "./public",

    "read-only": false,

    "no-cors": false,

    "no-gzip": false,

    "routes": "route.json"

}

启用:

# 默认使用:json-server.json配置文件

$ json-server --watch app.js

# 指定配置文件

$ json-server --watch -c jserver.json db.json

2.模块引用

(1)安装

$ npm install json-server


(2)创建mock-server.js文件(除此之外,与全局使用同理,需准备db.json或db.js文件)

mock-server.js形如:

const jsonServer = require('json-server');

const $db = require('./db');    // db.json。或返回db.json数据格式的,db.js文件

const server = jsonServer.create();

const middlewares = jsonServer.defaults();

const router = jsonServer.router($db);


server.use(router);

// Set default middlewares (logger, static, cors and no-cache)

server.use(middlewares);

// To handle POST, PUT and PATCH you need to use a body-parser

server.use(jsonServer.bodyParser);


server.listen(3001, () => {    

    console.log('JSON Server is running at 3001');

});


(3)使用

$ node mock-server.js

启动成功


(4)自定义路由

使用:jsonServer.rewriter()

const jsonServer = require('json-server');

const $db = require('./db');    // db.json。或返回db.json数据格式的,db.js文件

const $routeHandler = require('./routeHandler');  // 引入自定义路由配置文件

const server = jsonServer.create();

const middlewares = jsonServer.defaults();

// 路由格式处理。需要加在 server.use(router) 前

server.use(jsonServer.rewriter($routeHandler($db)));

const router = jsonServer.router($db);


server.use(router);

// Set default middlewares (logger, static, cors and no-cache)

server.use(middlewares);

// To handle POST, PUT and PATCH you need to use a body-parser

server.use(jsonServer.bodyParser);


server.listen(3001, () => {        

    console.log('JSON Server is running at 3001');

});

「注」

routeHandler.js需要返回一个json对象,指明路由配置规则。参考route.json。

另外,可以把整个路由挂载到另外一个地址

server.use('/data', router);

即,所有/data/*的请求,都等同于/*请求。


(5)mock数据访问

与全局使用部分介绍规则完全相同。


(6)其他高级用法(mock-server.js)

json-server依赖express开发而来,可进行深度定制。

·自定义请求返回值

// 自定义post请求的返回值

server.post(filePath, (req, res) => { 

    var contentText = fs.readFileSync(filePath, 'utf-8');

    res.send(contentText);

});

// 自定义get请求的返回值

server.get(filePath, (req, res) => {

        var contentText = fs.readFileSync(filePath, 'utf-8');

        res.send(contentText);

});

「注」

这里的filePath,不可以使用变量,需要指定具体值。如:/data/data1。

这里的server.post和server.get,相当于注册两个监听事件,监听指定的接口,并在相应接口,被前端访问时,执行回调函数。

·自定义输出内容

router.render = (req, res) => {

    res.jsonp({

        body: res.locals.data

    });

}

·自定义用户校验

server.use((req, res, next) => {  

    if (isAuthorized(req)) {  // add your authorization logic here

        next();

        // continue to JSON Server router

     } else {

        res.sendStatus(401);

    }

});




【附】

json-server内置实现的过滤字段(用于属性字段的过滤,可直接使用)

「注」过滤字段,只针对数组数据。(毕竟只有数组需要过滤)

_gte: 大于等于

_lte: 小于等于

_ne: 不等于

_like: 包含

例:http://localhost:3001/data1?age_gte=20&age_lte=30

_page:访问第几页数据

_limit:一页多少条(默认一页10条)

_sort:设定排序字段

_order:设定排序的方式(升序:asc;降序:desc;默认升序)

例:http://localhost:3001/data1?_sort=age&_order=asc

_start:数据截取起始坐标

_end:数据截取终止坐标

_limit:截取数据条数

例:http://localhost:3001/data1?_start=0&_end=1

       http://localhost:3001/data1?_start=0&_limit=2

「注」

截取指定的那些数组项。使用类似Array.slice。

q:全文搜索关键字

_embed:关联子实体。用来获取包含下级资源的数据。

_expand:关联父实体。用来获取包含上级资源的数据。

【详解 —— json-server的关系图谱(类似数据库级联)】

有如下db.json(comments中的项,关联了postId。所以posts是上级资源、comments是下级资源):

{

    "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" }

}

说明:

comments每个item的postId,指明当前comment与posts的关联。

即:第一条comment指明,它关联posts中id=2的item,也就是 { "id": 2, "title": "post的第二个title", "author": "tangcaiye" } 这个对象。注意,这里的命名方式,严格遵循字面匹配。期望和posts数组进行关联时,关联id的key,叫做postId,期望和tests数组进行关联,关联id的key,就叫做testId。

访问测试_embed:

http://localhost:3001/posts?_embed=comments


http://localhost:3001/posts?_embed=comments

解析:

访问/posts接口,添加comments字段,初始化为空数组。并在comments接口中查找对应postId的数据项,添加到comments数组中。

如上例,_embed=comments,则给/posts接口的每一项,添加comments: [ ]。当comments接口的数据项指明了postId,如 { "id": 2, "body": "some comment2222", "postId": 1 },则在posts接口中,找到id等于1的item,即 { "id": 1, "title": "post的第一个title", "author": "typicode", "comments": [ ] },并把 { "id": 2, "body": "some comment2222", "postId": 1 } 这个的数据对象,添加到comments数组中去。

生成数据项:

 {

         "id": 1,

         "title": "post的第一个title", 

         "author": "typicode",

         "comments": [ { 

                "id": 2, 

                "body": "some comment2222", 

                "postId": 1 

         } ] 

 }

访问测试_expand:

http://localhost:3001/comments?_expand=post


http://localhost:8081/comments?_expand=post

解析:

访问/comments接口,并为它的每一个数据项,扩展url指明的字段。字段的值,取决于当前comment数据项的关联id值。

如上例,_expend=post,则给/comments的每一个包含postId的项,在posts中找到对应的post,添加到comment中。如:对 { "id": 1, "body": "some comment1111", "postId": 2 } 进行扩展。posts中,postId为2的项是 { "id": 2, "title": "post的第二个title", "author": "tangcaiye" },则扩展后:

生成数据项:

{

     "id": 1, 

    "body": "some comment1111",

    "postId": 2,

    "post":  { 

            "id": 2, 

            "title": "post的第二个title", 

            "author": "tangcaiye" 

        }

}





【其他】json-server相关启动参数


语法:json-server [options] <source>    「注」source可以是json文件或js文件(返回形如上文的json数据)

options列表:

options列表



#参考:

https://www.cnblogs.com/fly_dragon/p/9186722.html

https://segmentfault.com/a/1190000010449453

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容