跳到主要内容

JSON 转 Ruby Hash:符号键、箭头语法与 Rails fixture 实战

把接口返回的 JSON 变成地道的 Ruby Hash 字面量,讲清符号键和字符串键怎么选、=> 箭头语法何时用、嵌套结构与对象数组如何映射,以及给 Rails 测试做 fixture 的具体路子。

发布于 作者 李雷
#ruby #json #rails #数据转换

JSON 转 Ruby Hash:符号键、箭头语法与 Rails fixture 实战

写 Ruby 的人多半都干过这件事:抓到一段接口 JSON,想塞进 spec 当 fixture,结果对着花括号一个键一个键手敲,逗号漏一个就报错。这篇把 JSON 到 Ruby Hash 这条路讲透,重点说三件容易卡住的事:符号键还是字符串键,什么时候得用 => 箭头,以及嵌套结构和对象数组怎么对齐成 Ruby 里能跑的字面量。

符号键、字符串键和 => 箭头到底怎么选

Ruby 的 Hash 键有三种常见写法,各有各的场合。

现代简写符号键 name: value 是日常首选。符号只被 intern 一次,比较起来快,而且 Rails 的 params、各种配置和大多数 gem 默认都吃符号键。

箭头形式 :name => value 在键不是合法 Ruby 标签时派上用场。比如键叫 first-name,带连字符,简写形式根本写不出来,这时退回到 :"first-name" => value 才能解析。

字符串键 "name" => value 留给那种要镜像外部 JSON、之后还得再序列化回去的场景,或者键可能撞上 Ruby 保留字的时候。

一个真实的坑:很多人以为简写符号对所有键都管用,把 :"first-name" => 1 手改回 first-name: 1,结果整段字面量报语法错。带特殊字符的键老老实实留着箭头形式。

一段真实的 JSON 转 Ruby Hash

光说不练没意思,看一段。假设接口返回:

{
  "id": 1,
  "login": "octocat",
  "company": null,
  "addr": { "city": "Beijing", "zip": "100000" }
}

用符号键简写模式转成 Ruby Hash 字面量,出来是这样:

{
  id: 1,
  login: "octocat",
  company: nil,
  addr: {
    city: "Beijing",
    zip: "100000"
  }
}

几个细节值得注意。JSON 的 null 变成 Ruby 的 nil,因为 nil 就是 Ruby 表示缺失的唯一方式,正如 null 之于 JSON。整数 1 照搬,字符串用双引号包裹并做好转义。嵌套的 addr 对象渲染成嵌套 Hash,每层缩进两个空格,直接放进 .rb 文件或 irb 会话都不用再整形。我平时就把这段输出粘进 JSON 转 Ruby 工具,改完键风格再复制走,比手敲快太多。

拿来做 Rails fixture 和测试工厂

冷启动期我自己写工具,测试里全是从日志扒下来的真实响应。流程很固定:在日志里抓到一段 API JSON,粘进转换器,符号键保持简写,把输出直接复制到 let 块或者 FactoryBot 的 trait 里。null 字段出来是 nil,嵌套对象是嵌套 hash,fixture 和线上形状完全一致,一个花括号都不用重打。这点在做契约测试时尤其省心,因为你 mock 出来的数据形状必须和真实 wire 格式对齐,手敲很容易漏字段。

db:seed 也是同样的路子。同事丢来一份参考行的 JSON 导出,把对象数组粘进来,留在 Hash 模式用符号键,得到一个 Ruby hash 数组,直接喂给 seeds.rb 里的 Model.create!(attrs)

嵌套结构和对象数组的折叠

嵌套对象好说,JSON 里几层 Ruby Hash 就几层,整棵树原样保留。

麻烦的是对象数组里各元素形状不一致的情况。比如 [{"id":"a"},{"id":"b","note":"x"}],第一个元素没有 note。转成 Hash 数组时,工具会把缺失的键显式补成 note: nil:

[
  { id: "a", note: nil },
  { id: "b", note: "x" }
]

这样每条记录的属性集都一样,Model.create!(attrs) 循环不会因为某条少了字段而行为不一致。如果你切到 Struct 模式,这套折叠逻辑更明显:所有元素的键被并进一个共享 Struct,缺的传 nil,而不是生成两个几乎重复的类。

输入坏了先格式化再转

接口 JSON 有时带尾随逗号、单引号或者多余的转义,直接转会被解析器顶回来。遇到这种先用 JSON 格式化工具把结构理顺、确认合法,再喂给转换器,能少走不少弯路。Ruby 之外如果你还在多语言项目里来回搬数据,同一份接口 JSON 也能转成别的类型字面量,工具箱里另有对应的入口。

小结

JSON 转 Ruby Hash 的核心其实就三句话:键风格按场景选,符号键日常用、箭头键应付特殊字符、字符串键镜像外部数据;null 一律变 nil;对象数组缺的键显式补 nil 保持形状一致。把这条路走顺,Rails 的 fixture、seed 和控制台调试都能省下大把手敲的工夫。


Made by Toolora · Updated 2026-06-13