跳到主要内容

JSON 转查询字符串(query string)实战:数组、嵌套与 URL 编码怎么处理

把 JSON 对象拼成 URL 查询字符串看着简单,真要对上后端、处理数组和嵌套、做好 URL 编码就有不少坑。这篇讲清三种数组写法、方括号嵌套和往返转换。

发布于 作者 李雷
#json #query-string #url-encoding #前端

JSON 转查询字符串(query string)实战:数组、嵌套与 URL 编码怎么处理

写接口的人迟早会遇到这件事:手里有个 JSON 对象,要把它拼成 URL 后面那截 key=value&key=value,贴到浏览器地址栏、curl 或 Postman 里跑一个 GET 请求。听上去就是几行字符串拼接,真动手才发现,数组怎么放、嵌套怎么展开、空格和中文怎么编码,每一步都能把请求拼坏。

查询字符串到底是什么

URL 里 ? 后面的部分就是查询字符串。它是一串用 & 连起来的键值对,每对中间用 = 分隔,比如 q=opus&page=2&size=20。它最常见的用途有三个:发 GET 请求时带参数、给已有 URL 拼上跳转或筛选条件、调接口时把参数摊开方便对照排查。

要点在于,查询字符串本身是纯文本,没有类型概念。JSON 里的 {n:42, ok:true} 拼出来是 n=42&ok=true,解析回去拿到的是字符串 "42""true",不是原来的数字和布尔值。这一点接收端必须自己转回去,工具不该替你猜,因为猜会把前导零和大整数搞坏。

URL 编码:那些必须转义的字符

直接把值塞进 URL 是危险的。值里如果带空格、斜杠,或者本身就含 &= 这种分隔符,不转义就会把整条 URL 读歪。正确做法是每个键和每个值都过一遍 encodeURIComponent:空格变 %20,斜杠变 %2F,值里的 &= 被转义掉,免得被当成分隔符。

举个会出事的例子,{"raw":"x=1&y=2"} 不编码就成了 raw=x=1&y=2,后端会读成三个参数。过一遍编码后是 raw=x%3D1%26y%3D2,一个参数,值原样保留。中文这种非 ASCII 字符会按 UTF-8 做百分号编码,{"name":"你好"} 变成 name=%E4%BD%A0%E5%A5%BD。这些都不该手动去敲,交给编码函数。

数组的三种写法,对上后端是关键

同一个数组,不同后端认不同写法,这是最容易踩的坑。常见三种:

  • repeat:tag=red&tag=blue,重复同一个键。Express、Rails、Go 的 r.URL.Query() 都直接认。
  • bracket:tag[]=red&tag[]=blue,带方括号。qs 库和 PHP 要这个。
  • comma:tag=red,blue,逗号紧凑,搜索类 API 常用。

挑哪种取决于你正在调的服务。有一点要留意:逗号写法是单向有损的,值里本来就带逗号时,解析回来分不清是分隔符还是内容,数组重建不了。只要这条串以后可能被读回 JSON,就用 repeat 或 bracket。

嵌套对象走方括号路径

对象有层级时,展开成方括号路径。{"user":{"name":"ada"}} 拼成 user[name]=ada,再深一层 {"user":{"address":{"city":"oslo"}}} 就是 user[address][city]=oslo。这里结构用的方括号保持原样不做百分号编码,这样串既好读又能原样解析回去,只有名字和值被编码。这套约定 qs 库、PHP、Rails 都认。

顺带说一句,前端自带的 URLSearchParams 在这件事上帮不上忙。它只处理扁平的字符串键值对,new URLSearchParams({user:{name:'ada'}}) 给你的是字面文字 user=[object Object],数组重复项也不会按预期展开。要处理有深度的数据,得自己走方括号序列化。

一个完整的输入输出例

把上面几条凑一起看。输入这个搜索配置:

{ "q": "opus 4", "tags": ["ai", "tools"], "page": { "size": 20 } }

选 repeat 数组写法,打开开头的 ?,拼出来是:

?q=opus%204&tags=ai&tags=tools&page[size]=20

注意 opus 4 里的空格自动变成了 %20,数组 tags 摊成两个重复键,嵌套的 page 走了方括号。这条串接到接口地址后面就能直接发请求,不用数 & 符号,也不会漏掉转义。

我自己调一个老项目的搜索接口时,就因为手拼漏了把查询词里的空格转义,后端把它截成两段,排查了快二十分钟才发现是这种低级问题。后来固定用工具拼,顺手把排序和跳空打开,空字符串、null、空数组这些半填字段从输出里消失,链接只剩真正有用的参数,签名做缓存键时两个逻辑相等的对象也能拼出逐字节一样的串。

往返转换:拼出去也读得回来

好的转换是双向的。把 JSON 拼成查询字符串后,反过来也要能把任意查询字符串解析回格式化的 JSON:重复键 tag=red&tag=blue 合并成数组,user[name]=ada 嵌套成对象,+%XX 都解码回来。因为两个方向共用同一套方括号约定,repeat 和 bracket 写法下,JSON 转 query 再转回 JSON 是干净的往返,数据不会被悄悄改坏。

你可以在 JSON 转 Query String 里直接试这套流程,左边粘对象、右边读回 JSON,改哪边另一边都跟着重拼。如果只是想单独对一段文本做编码解码,用 URL 编码解码工具 更直接。

把这几件事分清楚,数组写法对上后端、嵌套走方括号、每个值都过编码,JSON 拼查询字符串这件小事就不会再回头咬你。


Made by Toolora · Updated 2026-06-13