封装一个 axios url encoding serialize util
封装一个 axios url encoding serialize util
该 util 遵从的是 Json API,即 swagger, 这一规范,可以将对应的 query 进行 encoding。
主自用,使用 TS,参考对象为 lodash-contrib。
axios 默认传递到后台的数据为 json 格式,官方在文档:URL-Encoding Bodies 中建议在浏览器环境下可以直接使用 URLSearchParams 或是 qs,使用方法如下:
-
URLSearchParams
const params = new URLSearchParams(); params.append('param1', 'value1'); params.append('param2', 'value2'); axios.post('/foo', params);
-
qs
const qs = require('qs'); axios.post('/foo', qs.stringify({ bar: 123 }));
ES6:
import qs from 'qs'; const data = { bar: 123 }; const options = {method: 'POST',headers: { 'content-type': 'application/x-www-form-urlencoded' },data: qs.stringify(data),url, }; axios(options);
我们的 JSON 规范遵从的是这一条:Json API,直接使用 URLSearchParams
好像是行不通的,因为有一些 filter 会使用 [
和 ]
,如:/author/1/book?filter[book]=genre=='Science Fiction';title==The*;price.total>100.00
,之前直接使用 URLSearchParams
似乎就报错了。
当然,也有可能是因为 encoding 没有完全转换的关系。
出于同样的原因,直接使用 qs
也存在一定的问题,似乎可能是因为需要重新修改 encoder、queryPrefix 等因素,总之没有能够在有限的时间内完成调整。
最终还是稍微修改了一下 lodash-contrib 中的 toQuery
,具体实现如下:
import _ from 'lodash';// some of the util functions are from lodash-contrib but in TS form, credit: https://github.com/node4good/lodash-contrib
// recreated here due to lodash-contrib does not have TS support and cannot be used in the project.
type validQuery = string | number | boolean;type validQueryObj =| { [key: string]: validQuery | validQueryObj }| validQuery[]| validQuery;const buildParams = (prefix: string | number,val: validQueryObj,top = true
): string => {if (_.isUndefined(top)) top = true;if (_.isArray(val)) {return _.map(val, function (value, key) {return buildParams(top ? key : prefix + '[]', value, false);}).join('&');} else if (_.isObject(val)) {return _.map(val, function (value, key) {return buildParams(top ? key : prefix + '[' + key + ']', value, false);}).join('&');} else {return encodeURIComponent(prefix) + '=' + encodeURIComponent(val);}
};export const toQuery = function (obj: validQueryObj): string {return buildParams('', obj);
};
使用方式如下:
export const fetch = async ({apiMethod,uri,params,
}: FetchProps): Promise<AxiosResponse<any, any>> => {return await axiosInstance({method: apiMethod,url: uri,params,paramsSerializer: (params) => {return toQuery(params);},});
};
type guard 目前不是最好的实现,还是需要根据 generics 进行对应的修改,不过这应该算是一个比较通用的解决方案了。