背景
在 Jira 里用 JQL 搜完一堆单子,想把链接发给同事,复制地址栏一看,画面是这样的:
(Open%2C%20%22In%20Progress%22)明明在搜索框里输入的是干干净净的一行:
project=ZHANDcomponent="VELA"ANDstatusin(Open,"In Progress")第一反应往往是「是不是编码坏了」「中文是不是乱码了」。
都不是。这叫URL 百分号编码(percent-encoding,也叫 URL encoding),是浏览器自动做的,规范出自 RFC 3986。查询本身没有任何问题。
为什么必须编码
URL 是一个有语法的字符串,?分隔查询串、&分隔参数、=分隔键值、#开始锚点。如果把一个恰好含有=或&的值直接塞进去,解析器就没法分辨哪个=是语法、哪个=是数据。
同时 URL 在设计上只允许一小部分 ASCII 字符直接出现(字母、数字和-_.~),其余一律需要转义。中文更是完全不在 ASCII 范围内。
解决办法很朴素:把字符按 UTF-8 转成字节,每个字节写成%加两位十六进制。
对应关系
以开头那个链接为例:
| 原字符 | 编码结果 | 说明 |
|---|---|---|
| 空格 | %20 | 字节 0x20 |
= | %3D | 字节 0x3D |
" | %22 | 字节 0x22 |
, | %2C | 字节 0x2C |
升 | %E5%8D%87 | UTF-8 三字节 E5 8D 87 |
级 | %E7%BA%A7 | UTF-8 三字节 E7 BA A7 |
所以%E5%8D%87%E7%BA%A7就是「升级」两个字 —— 每个汉字占 3 个字节,于是变成 6 组%XX。看着吓人,其实只是两个字。
把整串反解回去,得到的正是原样的 JQL:
project=QZHANDcomponent="VELA"ANDstatusin(Open,"In Progress")编码没出错,查询是对的。
一个容易被忽略的细节:括号为什么没被编码
仔细看原链接,(Open%2C%20%22In%20Progress%22)里逗号和引号都编码了,但小括号是原样保留的。
这不是 Jira 偷懒。RFC 3986 把字符分成几类,(和)属于sub-delims,在查询串这个位置出现是合法的,因此可以不编码。换句话说,「哪些字符需要转义」存在一个可调的安全字符集,不同库的默认值不一样。
用 Python 验证一下就很直观:
fromurllib.parseimportquote quote('(')# '%28' —— 默认把括号也编码quote('(',safe='()')# '(' —— 声明括号安全,保持原样两种输出都是合法 URL,服务端解码后得到的字符串完全相同。所以看到同一个查询在不同工具里生成的链接长得不一样,不必怀疑哪个是错的。
实用技巧
快速解码一串 URL
想确认一个长链接到底在查什么,不用肉眼翻译:
python3-c"from urllib.parse import unquote; import sys; print(unquote(sys.argv[1]))""粘贴URL"Node 环境更短:
node-e"console.log(decodeURIComponent(process.argv[1]))""粘贴URL"浏览器控制台里也可以直接decodeURIComponent('...')。
不要手工拼编码
需要一个带复杂 JQL 的链接时,正确做法是:在 Jira 的 Advanced 搜索框里把 JQL 改好、回车,然后复制地址栏。编码交给浏览器,不要自己敲%20。
分清两种 Jira 链接
这一点很容易踩:
| 路径形式 | 实际含义 |
|---|---|
/browse/ZH-3321?jql=... | 单个 issue 详情页,jql只为「上一条/下一条」提供上下文 |
/issues/?jql=... | 搜索结果列表页,可收藏、可分享 |
想分享搜索结果,把/browse/<ISSUE-KEY>换成/issues/即可。
更干净的方案:保存为筛选器
Jira 支持把查询存成 filter,之后链接变成:
https://jira.cn/issues/?filter=12345短、可读、改条件不用换链接,团队共享时明显优于一长串%XX。
小结
- URL 里的
%XX是百分号编码,浏览器自动生成,正常现象。 - 规则是「字符 → UTF-8 字节 → 每字节写成
%+ 两位十六进制」。 - 一个汉字通常是 3 字节,所以会展开成 3 组
%XX,视觉上膨胀但语义不变。 - 哪些字符需要转义有一定弹性(如括号可保留),同一查询存在多种合法编码形式。
- 遇到看不懂的长链接,用
unquote/decodeURIComponent解码,别靠猜。 - 分享 Jira 搜索结果用
/issues/?jql=...,长期复用优先保存为 filter。
参考
- RFC 3986 — Uniform Resource Identifier (URI): Generic Syntax, §2.1 Percent-Encoding
- MDN — encodeURIComponent()
- Python 文档 — urllib.parse
- Atlassian — Advanced searching with JQL