javascript - 反序列化查询字符串
问题描述
如何使用查询字符串(反)序列化嵌套字典?我查看了有关如何序列化嵌套对象的其他帖子,但我找不到在反序列化时保留原始字典层次结构/布局的便捷方法。
假设我有以下输入:
const params = {
id: 1,
filters: {
price: {
min: 101,
max: 300
}
},
sorters: {
sortBy: 'price',
order: 'desc'
}
}
如何使用查询字符串来回转换?
我可以使用 jquery 将其转换为查询字符串$.param
,但是当我尝试将其转换回原始字符串时,params
它是不正确的:
Object.fromEntries(new URLSearchParams($.param(params)))
输出:
{
"id": "1",
"filters[price][min]": "101",
"filters[price][max]": "300",
"sorters[sortBy]": "price",
"sorters[order]": "desc"
}
解决方案
正如聊天中所讨论的那样 - 似乎您希望能够在客户端和服务器上使用相同的查询条件对象图表示(这是合理的) - 好消息是因为您的对象图具有一致的设计您可以编写一个简单的函数,将图形序列化为更简洁的 URI 查询字符串表示,而无需冗余参数名称前缀或浪费大括号/冒号/引号空间...
总结一下:
- 对象的唯一可变部分
params
是filters:
子对象。id
和sorters
部分有一个固定的布局 - 这意味着有一个filters[]
部分是不必要的。
所以这:
const params = {
id: 1,
filters: {
price: {
min: 101,
max: 300
}
},
sorters: {
sortBy: 'price',
order: 'desc'
}
}
可以序列化为:
id=1&price_min=101&price_max=300&sortBy=price&dir=desc
下面是一些逻辑,可以将这样的查询字符串反序列化回params
您最初拥有的对象:
const queryObject = {
id: null,
filter: {},
sorters: {}
};
const qs = new URLSearchParams( "id=1&price_min=101&price_max=300&sortBy=price&dir=desc" );
for(const [key, value] of qs) {
if( key === 'id' ) queryObject.id = value;
else if( key === 'sortBy' ) queryObject.sorters.sortBy = value;
else if( key === 'dir' ) queryObject.sorters.order = value;
else {
if( key.endsWith("_min") || key.endsWith("_max") ) {
const name = key.substring(0, key.indexof("_"));
if( !name in queryObject.filters ) {
queryObject.filters[name] = {};
}
if( key.endsWith("_min") ) {
queryObject.filters[name].min = value;
} else {
queryObject.filters[name].max = value;
}
}
else {
queryObject.filters[key] = value;
}
}
}
序列化params
到URLSearchParams
也很简单:
const qs = new URLSearchParams();
if( 'id' in params ) qs.set('id', params['id']);
if( 'sortBy' in params.sorters ) qs.set('sortBy', params.sorters.sortBy);
if( 'order' in params.sorters ) qs.set('dir', params.sorters.order);
for( const key of params.filters ) {
if( typeof(params.filters[key] === 'object') {
qs.set(key + '_min') = params.filters[key].min;
qs.set(key + '_max') = params.filters[key].max;
}
else {
qs.set(key) = params.filters[key];
}
}
推荐阅读
- angular - 如何在 Ionic 3 的所有页面中使用相同的页脚?
- mysql - 仅获取员工人数最多的部门
- ios - webservice的输出没有使用alamofire快速提供所需的json
- pdf - 跟踪和输出 LaTeX 文档修订到 PDF 之间的更改/差异?
- docker - docker stack deploy 生成的图像带有
标签和不同的图像尺寸 - javascript - 将值从类方法传递给反应组件
- python - 如何为 dask 数据框创建自定义图表?
- ruby-on-rails - 如何将 before_action 与 :unless 和 params 一起使用
- angular - 订阅()在Angular 5中返回未定义而没有控制台
- laravel-5 - 在远程桌面上开发没有互联网的 laravel 项目