JSON 与 Properties 互转

JSON 与 Java Properties 风格键值文件互转

JSON 与 Properties 互转:扁平化、数组与编码约定

Properties 的模型是"扁平的键值列表"

Java 的 .properties 文件(以及各种沿用它的配置格式)本质上是一串平铺的键值行:

db.host=127.0.0.1
db.port=3306
list=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]=a
list[1]=b
按带下标的键绑定成列表Spring 的 @ConfigurationProperties
list.0=a
list.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。