jsonpath做接口封装使用技巧
作者:德莱厄斯
前言
jsonpath是一个可以在复杂的json数据中根据用户指定的规则找到特定数据的库。
本文利用jsonpath对接口进行封装,旨在写一个对前端友好的、易维护的、高扩展性的、可读的api json
如果同学知道xPath,那么可以轻松的掌握jsonpath,如果从没听说过这两个东西,可以根据第一小节快速了解。写法不拘泥于以下代码,内容仅提供思路。
快速开始 jsonpath
let obj = {...} let queryData = jsonpath.query(obj,"$..[?(@.name=='ni')]")
上述语法意思为:
$:从根元素开始,也就是`$.`,后面的`.` 意思是递归查询,即查询到最后一级子节点。
[?()]:条件语句,其中`@.`代指当前节点,可以理解为`forof`中的项(item)
如上所示,jsonpath最常用的query方法,有两个参数,第一个是数据源,第二个是查询语句。
此外,jsonpath还常用nodes和paths查询键值的路径、value查询值等。
使用jsonpath封装api
封装axios
封装axios的过程没有用到jsonpath,我们在这里只对方法做了统一。
以封装get为例:
import getUrl from "./apis" // 这个就是你自己写的接口json,下面会讲 get(topic, data) { let url if (topic.indexOf('http') === 0 || topic.indexOf('https') === 0) { url = topic } else { url = getUrl(topic) } return new Promise((resolve, reject) => { axios.get(url, { params: data }) .then(response => { resolve(response.data) }, err => { reject(err) }) }) },
我们传入一个topic(主题),和一个data(参数)。
data需要根据方法的不同做不同的处理,比如post函数中就应该直接axios.post(api(topic), data),而不是用上述语法。
topic的作用是在api中找出对应的url,后面会讲到,这是用jsonpath做到的。
axios到这里就可以了,相信各位小伙伴也有自己封装的方法,其实也都大差不差,你依然可以使用你自己的axios。
封装api
我们一直希望有一个易于管理和使用的api封装的方法,使用jsonpath可以轻松的做到这一点,我们完全可以写一个只给人类看的api文档,而不用考虑格式是否容易被读取。
比如,我们可以把api.js写成这样:
const apis = { mainDomain: { baseUrl: "https://yourmainDomain.com", uri: { introduction: { topic: "introduction", uri: "/introduction", pramas: { appCode: String, type: Number } }, someData: { topic: "someData", uri: "/somepath/somewhere/someData", }, } }, other:{...} }
由上可见,我们将api以 域名>uri+参数的形式写成了一个大的对象,就像写一个文档一样,这个格式的数据很有利于开发人员阅读,我们清楚的知道每个接口来自哪台主机、它的参数是什么,如果你愿意,你完全可以加一个method字段,那样我们就可以知道它的方法是什么。总之,你可以通过加字段的方式对这个文档进行维护,直到这个文档有你想要的一切信息,并且你自己可以看得懂。
如果没有jsonpath,我们可能需要对这个json进行一个稍微复杂的遍历,以找出我们需要的完整接口地址。
而根据以上结构,我们使用jsonpath很容易的就可以确定一个接口的完整地址,以及它需要的参数
const getUrl = (topic) => { let path = jsonpath.paths(apis, `$..[?(@.topic=='${topic}')]`) let { baseUrl } = jsonpath.query(apis, `$.${path[0][1]}`)[0] let { uri } = jsonpath.query(apis, `$..[?(@.topic=='${topic}')]`)[0] return baseUrl + uri //返回完整api地址 } export default getUrl //这里就是暴露刚刚用到的方法
只需要传入一个topic,即可根据topic找出完整的地址。topic可以根据接口地址某字段取值或者直接取一个根接口功能高度相关的字符,比如,取用户信息的接口,我们把topic写成getUserInfo,管他接口长什么样子,我们调用只需要:
let userInfo = await request.get('getUserInfo')
根据上述思路,我们需要做的几步分别是:
- 根据自己的喜好封装axios
- 根据自己的喜好写一个接口json
- 根据自己写的json编写jsonpath查询
做完这三步后,就可以使用了。
一般我们把请求和接口json分开,假如我们定义request.js和api.js
那么,在request 中引入api.js的getUrl方法,用来解析开发者传入的topic,并返回一个axios的promise对象即可。我们将各种方法放在一个大对象中,比如:
import axios from "axios" import api from "./apis" import qs from "qs" const request = { //...post...get...... } function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i].trim(); if (c.indexOf(name) == 0) return c.substring(name.length, c.length); } return ""; } export default request
像这样,就完成了全部封装流程
完成后的效果
用起来的感受就像下面:
import request from '@/utils/request'; let bugsData = await request.get('getBugsData', { beginTimeS: time.begin, endTimeS: time.end }) let bugsData = await request.post('setUserInfo', { nickName: "德莱厄斯", }) let bugsData = await request.put('someApi', { someKey: "someValue", })
可以看到,在使用此方法封装后,调用时,只需要传入一个字符串,一个对象代表参数即可,且不用随着method的变化更换参数格式,因为在封装axios时,我对他们做了统一处理,无论我们要调用get还是post,都只需按照一个格式写请求即可。
在这种封装模式下,是很容易拓展的,你可以按照自己的喜好给它加各种拦截器。
以上就是jsonpath做接口封装使用技巧的详细内容,更多关于jsonpath接口封装的资料请关注脚本之家其它相关文章!