JSON 与 Properties 互转
JSON 与 Java Properties 风格键值文件互转
JSON 与 Properties 互转:扁平化、数组与编码约定
Properties 的模型是"扁平的键值列表"
Java 的 .properties 文件(以及各种沿用它的配置格式)本质上是一串平铺的键值行:
db.host=127.0.0.1db.port=3306list=a,b
它没有嵌套、没有数组、没有类型——只有字符串键和字符串值。所以和 JSON 互转时,层次关系必须靠约定来表达,而这些约定不是标准,是各框架各自实现的。
嵌套靠点号,但点是键名的一部分
把 JSON 的 {"db":{"host":"127.0.0.1"}} 展开成 db.host=127.0.0.1,这是最通行的做法(Spring Boot 的松散绑定就是围绕它设计的)。
问题在于歧义:键名里本来就可能含点号。下面两种 JSON 展开后得到完全相同的一行:
{"db":{"host":"x"}}→db.host=x{"db.host":"x"}→db.host=x
反向解析时无法区分。有些实现用转义(db\.host)来消歧,但这不是标准,不同读取方不一定认。所以往返转换不是严格可逆的:如果配置里的键名含点号,务必先确认读取方的约定,或者干脆避免在键名里用点号。
数组没有原生表示
Properties 只有字符串值,数组只能靠约定,常见的有三种,互不兼容:
| 写法 | 读取方式 | 典型来源 |
|---|---|---|
list[0]=alist[1]=b | 按带下标的键绑定成列表 | Spring 的 @ConfigurationProperties |
list.0=alist.1=b | 下标当子键 | 部分框架的松散绑定 |
list=a,b | 按分隔符拆分 | 最常见,但值里不能含该分隔符 |
三种都不完美:第一种最明确但冗长;第三种最简洁但当元素本身含逗号(比如带逗号的 URL 或句子)就会拆错,需要额外的转义约定。工具会输出其中一种形式,使用时请对照你实际使用的框架文档,不要假设它一定匹配。
编码:这是最容易出乱码的地方
历史上 .properties 文件按 ISO-8859-1 读取,所以非 ASCII 字符必须写成 \uXXXX 转义——中文写成 \u4e2d 这种形式,文件本身保持纯 ASCII。这是 Java 平台长期的做法,原因是"一个字节序列在任何环境下都解释得一样"。
较新的版本(Java 9 之后对 ResourceBundle、以及 PropertyResourceBundle 的默认行为)改为按 UTF-8 读取。这就产生了版本差异:
- 写全 ASCII 转义 → 两种版本都能正确读,最稳。
- 直接写 UTF-8 中文 → 新版本正确,旧版本或按 ISO-8859-1 配置的读取方得到乱码。
所以面向不确定的运行环境时,用 \uXXXX 转义是最保险的做法。本工具在转换时可以输出转义形式,这就解决了"配置文件里想放中文"的问题。
格式细节
| 规则 | 说明 |
|---|---|
| 分隔符 | = 与 : 都合法,也可用空格;键名与值两侧的空白会被忽略 |
| 注释 | # 或 ! 开头 |
| 续行 | 行末加反斜杠,下一行接续(值很长时用) |
| 转义 | \n \t \\ \uXXXX;值里的 = 和 : 不必转义 |
| 重复键 | 后出现的覆盖先出现的(多数实现如此) |
重复键这条与 JSON 一样值得警惕:静默覆盖,没有警告。
工具怎么用
两个方向:把嵌套 JSON 展开成点号形式的键值行,或把键值行按点号还原成嵌套结构。同时支持将非 ASCII 字符输出为 \uXXXX 转义,以适配按 ISO-8859-1 读取的环境。
适合的场景:把 Spring Boot 的 application.properties 转成 JSON 便于程序处理或对比;把一份 JSON 配置生成出对应的 properties 供 Java 服务使用。全部在浏览器本地完成,含数据库连接信息的配置不会离开你的设备。
常见问题
为什么数字变成了字符串?
Properties 文件本质是纯文本,所有值都是字符串。反向转 JSON 时本工具不擅自推断类型,如需数字可在使用处自行转换。
注释会被保留吗?
JSON → Properties 不会生成注释;Properties → JSON 会跳过以 # 开头的注释行,但不会把它们写回 JSON。