博客 分享机制

用 URL Hash 分享 JSON:不上传服务器的原理、限制与用法

同事说「你那边 JSON 一格式化就对,我这边报错」。把文件传来传去很烦,截图又没法继续改。

URL Hash 分享把当前工具和输入写进地址栏的#后面。对方打开同一条链接,浏览器在本地还原左右栏;普通页面请求不会把这份数据发给服务器。

这和「贴到某个在线格式化网站再点分享」不是一回事。后者通常先把原文 POST 到别人的后端,再给你一个短链。Hash 分享没有这一步。

本文将说明:

先记住这一点:Hash 能用,是因为浏览器默认不把#后面发给服务器。但这既不是加密,也挡不住聊天软件把链接截断。下面按「原理 → 编码 → 长度 → 边界」把这件事拆开。

URL Hash 分享是什么

完整 URL 可以拆成两段:服务器会看到的部分,和只留在浏览器里的部分。

https://jsonnote.com/json/format.html#data=eyJvayI6dHJ1ZX0=

请求发给服务器 fragment / Hash(只留在浏览器)

JSONNote 的「分享」做的就是:把当前工具 id 和左侧输入编码进 Hash,再把整段location.href复制到剪贴板。对方打开后,页面脚本读location.hash,在他自己的浏览器里还原工具和文本。

  1. 1
    你在浏览器里点「分享」

    输入先转成 UTF-8,再编成 Base64,写成#tool=&data=

  2. 2
    把完整 URL 发给同事

    对方打开同一站点后,页面脚本读location.hash

  3. 3
    在对方浏览器里还原

    本地格式化、校验或 Diff。服务器只收到页面本身,没有这份 JSON。

这和把 JSON 处理放在浏览器里是同一条原则:计算发生在本地,分享也不经过我们的数据库。隐私边界写在隐私声明第 3 节。

为什么 Hash 不会上传到服务器

Fragment 不会进入 HTTP 请求

MDN 对 URL.hash 的说明WHATWG URL 标准里的 fragment#之后是 fragment identifier。浏览器导航时,HTTP 请求的 path / query 里不包含这段。

所以访问日志里通常只有:

服务器日志里常见的请求行
GET /json/format.html HTTP/1.1

而不是:

Hash 不会出现在请求行里
GET /json/format.html#data=……

这也是为什么 Hash 适合「我不想让站点存一份我的粘贴」,却不适合当保密通道:数据仍在完整 URL 里,只是默认不走这一跳网络。

和 Query String 的区别

写法 例子 服务器看不看得到 适合做什么
Query ?tool=json-format&data=… 会。出现在请求行、反向代理和 CDN 日志里 需要服务端读的参数
Hash #tool=json-format&data=… 普通页面请求不会带上 只给前端脚本用的状态

如果有人把同样的 Base64 放到?后面,效果看起来一样,数据却已经进了服务器日志。JSONNote 只写 Hash,就是为了避开这一层。

另外:Referer 通常也不带 fragment。你从分享页点到外链,对方站点一般拿不到 Hash 里的 JSON。这是浏览器默认行为,不是我们额外做的加密。

JSONNote 的分享链接长什么样

点「分享」后,Hash 是一组URLSearchParams

JSONNote 分享链接的 Hash 格式
#tool=json-format&data=<Base64>

tool

当前工具 id。打开链接后会切到对应工作区,而不是一律落到「JSON 格式化」。常见值包括json-formatjson-validatejson5json-pathjson-diff

只切换工具、不点分享时,地址栏会更新成#tool=…不含 data。这是为了记住你在用哪个工具,不会把编辑器里的内容写进历史记录。

data

左侧输入的 UTF-8 文本,再做 Base64。实现上等价于:

JavaScript · 编码
btoa(unescape(encodeURIComponent(input)))

encodeURIComponent是为了让中文和 Emoji 能过btoa。还原时走相反路径。这和 MDN 讨论的Unicode 字符串的 Base64 编码是同一类问题。

编码不是加密

Base64 的目的是「任意字节都能放进 URL」,不是「只有受信方能读」。任何人拿到链接,都可以在控制台还原:

JavaScript · 还原流程示例
const data = new URLSearchParams(location.hash.slice(1)).get("data");
decodeURIComponent(escape(atob(data)));

也可以把data=后面的字符串丢进本站的Base64 解码。没有口令,没有一次性链接,也没有过期时间。

一个完整示例

假设你在「JSON 格式化」里输入:

JSON · 左侧输入
{
  "name": "Ada",
  "role": "dev"
}

压缩成一行后是 27 字节:

JSON · 压缩后
{"name":"Ada","role":"dev"}

UTF-8 → Base64 得到 36 个 ASCII 字符(这段里没有+ / /,放进 URL 时不会再被百分号编码拉长):

Base64
eyJuYW1lIjoiQWRhIiwicm9sZSI6ImRldiJ9

完整 Hash:

完整 Hash
#tool=json-format&data=eyJuYW1lIjoiQWRhIiwicm9sZSI6ImRldiJ9

对方打开后看到同一段 JSON,可以继续格式化、做JSONPath 抽取,或和自己的响应做 Diff。若原文其实是带注释的配置,应改用JSON5 解析再分享输出,而不是把无法JSON.parse的文本直接丢给对方。

含中文时体积更明显。例如{"msg":"格式化后两边一致"}是 34 字节 UTF-8,Base64 后 48 字符;其中的/=再被 URL 编码,参数值会变成 54 字符。

链接会变多长

Hash 分享的硬限制不是「服务器上传上限」,而是整段 URL 还能不能完整送达对方浏览器

对一段近似纯 ASCII 的 JSON,实测数量级如下(含tool=json-format&data=的膨胀后长度):

原文大约 编码后 Hash 大约 经验限制
200 B 330 字符 聊天软件几乎都能完整送达
1 KB 1.4 KB 多数 IM 没问题,仍建议自己点开确认
8 KB 11 KB 浏览器通常能打开;部分客户端会截断
32 KB 44 KB 不要指望微信 / 邮件原文转发还能用

Chrome 能消化很长的地址栏,但中间还有一层:IM、邮件、短链服务、二维码。它们各自有更短的上限,而且很少告诉你「我把尾巴切掉了」。所以流程应是:

  1. 1
    点「分享」

    复制完整地址,不要只抄#后面一截。

  2. 2
    先在本机新标签打开

    确认工具和输入都在,再发给同事。

整份访问日志、数兆的导出文件,请本机粘贴或点「下载」。Hash 分享解决的是「复现一小段输入」,不是当网盘。

Hash 分享和其他方式比什么

方式 数据去哪 对方怎么接着干 适合 不适合
URL Hash 停在双方地址栏 打开同一站点即可继续处理 小段 JSON、复现报错 密钥、超大文件
聊天原文 聊天服务器 再复制一次 几行配置 进永久会话记录的内部数据
截图 图片 只能看,不能 parse 讲结构 还要继续格式化 / Diff
附件 / 网盘 第三方存储 下载后再贴 大文件 想避免多一份副本
在线 Paste 别人的后端 打开短链 需要公开、长期存放 任何不该离开本机的内容

团队里若已经有内网 paste 或工单附件,大段日志走原有通道更稳。Hash 的价值是:同一条链接同时带上「用哪个工具」和「输入是什么」,对方不用猜你点的是格式化还是校验。

使用时必须记住的边界

涉及真实隐私时,用离线或内网工具。这和「站点有没有登录框」无关。

常见问题

URL Hash 分享是什么?

把当前工具和输入编码进地址栏#后面。对方打开同一站点的同一条链接,浏览器在本地还原内容,而不把这份数据作为页面请求发给服务器。

Hash 里的数据服务器看得到吗?

普通页面请求不会把 fragment 发给服务器,访问日志里通常只有路径。但这不等于保密:拿到完整链接的人都能解码。

编码和加密有什么区别?

编码(这里是 Base64)保证文本能放进 URL,任何人都能反向还原。加密需要密钥,没有密钥就不能读。JSONNote 分享做的是前者。

Hash 分享可以用于密钥或 Token 吗?

不可以。链接一旦发出就无法收回,历史记录里也还在。密钥请走你们团队的密钥管理系统,不要进任何网页地址栏。

对方打开是空白的?

先检查 URL 是否在data=中间被截断;再确认打开的是同一个 JSONNote 站点,而不是只复制了#后面一截。超大文本请改用本机粘贴。

和 JSON 格式化、校验是什么关系?

分享只负责「原样带走当前输入和工具」。格式化、语法校验、JSON5、JSONPath、Diff 仍在对方浏览器里本地执行。需要先看结构,用JSON 格式化;需要定位Unexpected token,用校验JSON5

总结

URL Hash 分享本质上是:

本地工具状态 + 可逆编码 + 浏览器 fragment 不随请求上传。

它适合复现一小段 JSON 或配置,不适合当网盘,更不适合传秘密。用对了,你和同事对着同一左右栏说话;用错了,等于把明文贴进一条谁都能打开的地址。

← 返回博客