You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以最少字符数将JSON对象编码为URL搜索参数

问题描述

我开发了一款网页应用,支持用户调整参数创建、修改生成式艺术作品,完成后可以通过链接分享自己的创作(示例链接)。我的目标是把复现作品需要的所有数据都存在URL里,且URL总长度足够短,能满足推文280字符的长度限制。

朴素实现方案

最直接的实现思路是用JSON.stringify/JSON.parse处理配置数据,再把生成的字符串做base64编码。这个方案可以正常运行,示例如下:

https://generativestudios.app/stained-glass?version=1&artwork=eyJzZWVkIjoiMjg5NjI1NDIiLCJzcGxpdHRpbmdTdHJhdGVneSI6IlNwbGl0IFJhbmRvbSBCYWxhbmNlZCIsImRlcHRoU3RyYXRlZ3kiOnsia2luZCI6IkluaGVyaXRlZCBEZXB0aCIsImRlcHRoIjo0fSwiZGlzdFN0cmF0ZWd5Ijp7ImtpbmQiOiJYIENlbnRyb2lkIn0sImppdHRlciI6MCwicGFsZXR0ZSI6eyJyZWQiOnsiYSI6MC40LCJiIjowLjU3OTAyMTk5Nzg4MjMxMTUsImMiOjAuNCwiZCI6MH0sImdyZWVuIjp7ImEiOjAuMiwiYiI6MC42MTE4ODc4NDg2MTc1MDUyLCJjIjowLjgsImQiOjB9LCJibHVlIjp7ImEiOjAuNiwiYiI6MC45MzA0MzA2NDU0OTUzOTQ4LCJjIjoxLCJkIjowLjZ9LCJtb2RlIjoiU01PT1RIIn0sInN5bW1ldHJ5IjpmYWxzZX0%3D

但这个方案生成的URL总长度有560字符,达不到要求。

现有优化实现方案

首先梳理待编码数据的类型定义:

// 需要编码到URL中的配置结构
type Settings = {
  seed: string;
  splittingStrategy: SplittingStrategy;
  depthStrategy: DepthStrategy;
  distanceStrategy: DistanceStrategy;
  jitter: number;
  palette: Palette;
  symmetry: boolean;
};

// 辅助类型定义
type SplittingStrategy =
  | "Split Random"
  | "Split Random Balanced"
  | "Split Middle";

type DepthStrategy =
  | {
      kind: "Max Depth";
      maxDepth: number;
    }
  | {
      kind: "Flip Depth";
      maxDepth: number;
      p: number;
    }
  | {
      kind: "Inherited Depth";
      minDepth: number;
    };

type DistanceStrategy =
  | { kind: "XCentroid" }
  | { kind: "YCentroid" }
  | { kind: "DistanceToPoint"; x: number; y: number };

type Color = {
  a: Number;
  b: Number;
  c: Number;
  d: Number;
};

type Palette = {
  red: Color;
  green: Color;
  blue: Color;
  mode: "MOD" | "SMOOTH";
};

目前已经落地的优化方向有四个:

  • 将对象键名缩短为单字符
  • 将字符串枚举值映射为单字符编码
  • 小数按实际业务需求保留1-2位精度,砍掉多余的无效小数位
  • 用CBOR替代JSON做序列化,减少格式冗余

经过以上优化后,编码部分的长度(不含http://...域名段)从498字符降到了170字符,已经满足当前需求:

# 朴素方案编码结果
eyJzZWVkIjoiMjg5NjI1NDIiLCJzcGxpdHRpbmdTdHJhdGVneSI6IlNwbGl0IFJhbmRvbSBCYWxhbmNlZCIsImRlcHRoU3RyYXRlZ3kiOnsia2luZCI6IkluaGVyaXRlZCBEZXB0aCIsImRlcHRoIjo0fSwiZGlzdFN0cmF0ZWd5Ijp7ImtpbmQiOiJYIENlbnRyb2lkIn0sImppdHRlciI6MCwicGFsZXR0ZSI6eyJyZWQiOnsiYSI6MC40LCJiIjowLjU3OTAyMTk5Nzg4MjMxMTUsImMiOjAuNCwiZCI6MH0sImdyZWVuIjp7ImEiOjAuMiwiYiI6MC42MTE4ODc4NDg2MTc1MDUyLCJjIjowLjgsImQiOjB9LCJibHVlIjp7ImEiOjAuNiwiYiI6MC45MzA0MzA2NDU0OTUzOTQ4LCJjIjoxLCJkIjowLjZ9LCJtb2RlIjoiU01PT1RIIn0sInN5bW1ldHJ5IjpmYWxzZX0%3D

# 优化方案编码结果
p2EAomF2omEAYQBhAQNhaQJhAaJhdqFhAGEAYWkAYQL7QBwAAAAAAAFhA6RhAKRhAABhARgjYQIYZGEDGChhAaRhABRhARg%2BYQIYZGEDGFBhAmEBYQOkYQAYGWEBGD5hAhg8YQMYUGEEaDE2MTA1NjQ3YQVhAWEG9A%3D%3D
进阶优化方案解答

你现在已经把通用序列化层面的优化做的比较充分了,后续如果需要在URL里存更多数据,还有这些可落地的手段:

额外压缩技巧

  • 位级硬编码:你的数据结构是完全固定的,根本不需要通用序列化附带的结构描述字段,可以直接给每个字段分配合适的比特位:比如3种分割策略只占2比特,对称性开关只占1比特,深度值如果上限不超过16只占4比特,0-1范围的小数如果保留2位精度,映射到0-99的整数只占7比特,所有字段按位拼接几乎零冗余,压缩率比CBOR这类通用格式高一大截。
  • 叠加通用压缩:二进制序列化完成后,可以直接用浏览器原生支持的DEFLATE算法再压一遍(对应CompressionStream/DecompressionStream API,不需要引入第三方库),结构化数据通常能再缩短30%-50%。
  • 差分存储预设:如果分割策略、调色板这类选项有内置默认值或者官方预设,URL里不用存全量参数,只存和预设不一样的字段即可,能省掉很多固定值占用的空间。
  • 替换编码格式:普通base64里的+、/、=三个字符在URL里会被百分号编码,一个字符占3个位置,换成base64url编码(用-替换+,_替换/,去掉末尾补位的=),能直接消掉这部分无效长度。

替代解决思路

如果后续数据量涨到实在塞不下280字符限制,也可以换方案绕开URL存数据的限制:

  • 短链方案:把完整作品配置存在服务端数据库,URL里只放一个短ID,用户访问时服务端拉取对应配置渲染即可,完全不受长度限制,缺点是需要后端支持,链接的可用性依赖服务存续。
  • 本地存储方案:如果不需要跨设备分享,也可以把配置存在用户浏览器的本地存储里,URL只放配置的哈希索引,本地打开直接读缓存就行,缺点是换设备/清缓存就会失效,适合临时保存场景。

base64编码选型结论

普通base64不是URL场景下的最优选择:

  • 普通base64的编码效率是3字节转4字符,空间利用率75%,而且存在需要URL转义的特殊字符,会额外增加长度。
  • 改造成本最低的替换项是base64url,和base64编解码逻辑几乎一致,没有需要转义的特殊字符,利用率同样75%,浏览器原生API就能支持,适配成本极低。
  • 追求更高空间利用率可以选自定义URL安全字符集的base85,编码效率是4字节转5字符,空间利用率80%,比base64多存5%左右的数据,只要避开URL保留字符设计字符集,实际表现会优于base64。
  • 不建议尝试base91、base122这类理论利用率更高的编码,其中包含大量URL保留字符,会被强制百分号编码,实际长度反而更长。

内容的提问来源于stack exchange,提问作者Frank Weslien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:42:09