跳到主要内容

JSON 转 Dart 类:fromJson / toJson, 空安全, Flutter 即用

JSON 转 Dart / Flutter 类:粘 JSON, 得到 final 字段、camelCase 命名、factory fromJson、toJson、空安全 T?、嵌套类, 还可选 @JsonSerializable 代码生成。

  • 本地处理
  • 分类 开发运维
  • 适合 格式化、校验、压缩或检查和代码相关的文本。
示例:
类型、空安全和 fromJson/toJson 是怎么推断的

每个 JSON 对象生成一个 Dart 类, 字段用 camelCase, 带命名构造函数, 默认还手写一个 factory X.fromJson(Map<String, dynamic>) 和 Map<String, dynamic> toJson()。嵌套对象抽成自己的命名类 (User.address → UserAddress), fromJson 会递归进去。当 Dart 字段名跟原始 key (snake_case、kebab-case) 不一致时, fromJson/toJson 读写的是原始 key, 让 JSON 往返不丢字段。整数推断成 int; 带小数的推断成 double; 一个数字有时是整数有时带小数会放宽到 num。对象数组会折叠成一个类 —— 某些元素缺的 key (或值为 null) 会变成可空 T?, 对应的构造参数去掉 required。只出现过 null 的值推断成 dynamic。打开 "json_serializable" 会改成生成 @JsonSerializable()、part .g.dart 指令、@JsonKey(name:) 改名和 _$XFromJson / _$XToJson 桥接, 配合 build_runner 代码生成。关掉空安全则适配 2.12 之前的旧 Dart。

这个工具能做什么

把任意 JSON 粘进来 (Dio 响应、Firebase 文档、Supabase 行、第三方 REST body), 就能拿到一组干净的 Dart 模型类, 可直接放进 Flutter 项目。每个对象 生成一个类, 带 `final` 强类型字段、命名构造函数、一个 `factory 类名.fromJson(Map<String, dynamic> json)` 和一个 `Map<String, dynamic> toJson()`。JSON 的 key 会被 camelCase 成合法的 Dart 标识符 (`site_admin` 变成 `siteAdmin`, `created-at` 变成 `createdAt`), 而 `fromJson`/`toJson` 读写的仍是原始线上 key, 所以模型往返不会丢字段。数字会 拆成 `int` 和 `double`, 一个值在某个样本里是整数、另一个样本里带小数时, 会 放宽到 `num`, 让两种字面量都装得下。空安全默认开启: 某些数组元素里缺的 key, 或值为 JSON `null` 的字段, 会变成可空 `T?`, 对应的构造参数去掉 `required`; 只出现过 null 的值推断成 `dynamic`。嵌套对象抽成自己的命名类 (`User.address` 变成 `UserAddress`), `fromJson` 会递归进去; 对象数组会折叠 成一个共享类, 而不是 N 个几乎一样的类, 标量数组变成 `List<T>.from(...)`。 想走 build_runner 代码生成? 打开 json_serializable, 工具就改成生成 `@JsonSerializable()`、`part 'name.g.dart';` 指令、改名用的 `@JsonKey(name:)`, 以及 `_$ClassFromJson` / `_$ClassToJson` 桥接, 而不是手写方法体。你可以切换 `final` 与可变字段, 也可以完全去掉 JSON 方法只留一个纯数据类, 还能关掉空安全 适配 2.12 之前的旧 Dart。一切都在浏览器里跑: 你粘的 JSON 不会离开标签页。 JSON 写错时会给出清晰的中英双语解析错误, 指到具体行列, 结果可通过分享链接 复现, 也能一键复制。

工具细节

输入
文本 + 数值 + 结构化内容
页面会根据工具类型展示文本框、数值控件、文件选择或结构化输入。
输出
即时结果 + 复制 + 下载
结果区优先给出可操作结果,支持项会显示复制、下载或可视化预览。
隐私
浏览器本地处理
主工具逻辑未发现外部 API 调用,输入通常留在当前标签页内处理。
保存 / 分享
可分享链接状态
关键设置会进入 URL,复制链接后别人能复现同一组参数。
性能预算
首屏 JS ≤ 25 KB
没有声明 WASM 依赖,适合快速打开和移动端使用。
适用场景
开发运维 · 程序员
分类和职业标签用于推荐相关工具、组织内链,并帮助用户快速判断是否适合当前任务。

怎么用

  1. 1. 输入

    把内容粘贴或拖入工具面板。

  2. 2. 处理

    点击按钮,在浏览器内本地处理,文件不上传。

  3. 3. 复制 / 下载

    一键复制结果或下载到本地。

JSON 转 Dart 类 适合怎么用

适合穿插在写代码、查问题、做 Review、上线前的小任务里。

适合开发场景

  • 格式化、校验、压缩或检查和代码相关的文本。
  • 把片段整理好再放进文档、工单、提交或交接材料。
  • 不切换工具,快速检查一个小 payload。

开发检查项

  • 压缩、混淆这类不可逆处理,先对副本操作。
  • 除非确认工具本地处理,不要粘贴密钥和敏感片段。
  • 转换后的代码上线前,仍要跑自己的测试或 lint。

下一步可以接着做

这些入口会把当前任务接到更完整的工具链里。

  1. 1 JSON 转 Kotlin 数据类 JSON 转 Kotlin data class, 粘 JSON 出 val 属性, camelCase 字段, 可空 T?, 嵌套类, 带 kotlinx.serialization @SerialName、Gson @SerializedName 或 Moshi @Json 注解。 打开
  2. 2 JSON 转 Java 类 JSON 转 Java POJO、record 或 Lombok @Data, 粘 JSON 出 camelCase 字段, 带 getter/setter, Jackson @JsonProperty 或 Gson @SerializedName, 嵌套类, 基本类型与装箱推断。 打开
  3. 3 JSON 转 TypeScript Interface JSON 转 TypeScript interface, 粘 JSON 出干净 interface, 数组元素合并为 union, 可选字段自动识别, 根类型名可命名。 打开

真实使用场景

  • 给 Dio 响应建模, 不用手写 fromJson

    你用 Dio 打了个接口, 想要一个强类型模型, 而不是拿 `response.data['user']['profile']['avatar']` 这种字符串 key 硬钻。 粘一个样本响应, 设好根类名, 复制生成的 Dart 就行。你会得到 `final` 字段、一个 `factory User.fromJson(Map<String, dynamic>)`, 以及给 请求体用的 `toJson()`, 嵌套对象也已经抽成各自的类并接好。原本要花 15 分钟手敲 `as String` 的活, 现在变成粘贴加复制, camelCase 改名 自动完成, 所以 `created_at` 在你的 widget 树里读作 `createdAt`, 但序列化回去仍是线上的 key。

  • 给 build_runner 项目生成 json_serializable 模型

    你的 Flutter 应用本来就跑 build_runner 配 json_serializable, 后端 刚给了你一个新 payload。打开 json_serializable 选项, 粘 JSON, 工具 就生成带 `@JsonSerializable()` 的类、`part 'user.g.dart';` 指令、 每个改名字段的 `@JsonKey(name: 'created_at')`, 以及 `_$UserFromJson` / `_$UserToJson` 桥接。文件放进去, 跑 `dart run build_runner build`, 生成的代码跟你代码库已有的约定完全一致, 不用再回头手动补注解。

  • 把 Firebase 文档转成不可变 DTO

    Firestore 给你的是一个类型混杂、字段可选的 `Map<String, dynamic>`。 粘一个有代表性的文档, 保持 `final` 开启, 模型就是不可变的, 这正是 Flutter 推荐的默认做法, 适合在 widget 之间流转的状态。某些文档没有的 字段会输出成可空 `T?`, 这恰好符合 Firestore 的现实: 不是每个文档都有 每个 key, 而带 null 守卫的 fromJson (`json['x'] == null ? null : ...`) 意味着缺字段时解析不会抛异常。

  • 让 Supabase 行对上强类型类

    Supabase 的 select 返回 snake_case 列名 (`user_id`、`is_active`、 `last_seen`)。粘一行进来, 工具会把 Dart 字段名 camelCase 化 (`userId`、`isActive`、`lastSeen`), 同时让 `fromJson`/`toJson` 绑定 原始列名, 所以模型不用自定义 converter 就能跟数据库往返。一个有时是 整数 (计数) 有时是小数 (平均值) 的数字会放宽到 `num`, 这样列第一次 返回浮点时不会触发运行时 cast 错误。

  • 消掉无类型 Map 访问带来的运行时类型错误

    靠 `data['items'][0]['price']` 取值, 直到某天后端在你期望数字的地方 发了个字符串, 应用就在生产环境崩了。用这个工具生成一个真正的类, 用 `fromJson` 解析一次, 之后每一处下游访问都是静态类型的, 分析器在编译 期就标出类型不匹配, 而不是让你的用户撞上红屏。对象数组会折叠成一个类, 所以哪怕一个列表有 200 项, 你也只需对一个强类型元素模型推理。

常见踩坑

  • 把每个数字都当成 int。JSON 只有一种数字类型, 所以一个在你样本里是 0、实际却带分或带平均值的字段会被推断成 int, 之后遇到 4.5 就静默地变成 cast 错误。本工具会把 int/double 联合放宽到 num, 但如果某字段在你样本里恰好都是整数、生产环境却可能带小数, 发布前请手动改成 double 或 num。

  • json_serializable 模式下忘了 build_runner。@JsonSerializable() 注解、part 'name.g.dart'; 指令, 以及 _$ClassFromJson / _$ClassToJson 引用, 全都依赖跑 dart run build_runner build 来生成 .g.dart 文件。把输出粘进去、跑代码生成, 并在 pubspec.yaml 里加上 json_annotation + json_serializable + build_runner。如果你只想要一个自包含文件, 就关掉 json_serializable, 用手写方法。

  • 改名时把线上 key 也改掉了。fromJson 之所以读 json['site_admin'], 正是因为这是 JSON 的 key, 哪怕 Dart 字段是 siteAdmin。如果你到处把字段改成 siteAdmin、连 map 的 key 也改成 'siteAdmin', 反序列化就会去找一个服务器根本不发的 key, 字段一直是 null。请在 fromJson/toJson 里保留原始 key (代码生成模式则用 @JsonKey(name:))。

隐私说明

你粘进来的 JSON 不会离开这个浏览器标签页。解析和类型推断走浏览器内建的 JSON.parse, 没有任何网络请求, 也不对文本框内容做 analytics。分享链接会把你 的输入和根类名编码进 URL 以便复现结果, 也就是说由你决定何时分享。如果 payload 敏感 (内部 ID、客户数据、生产响应), 直接复制生成的 Dart 代码, 不要 分享链接。只有选项 (final、空安全、json_serializable、fromJson/toJson) 会 存进 localStorage, 让你偏好的风格在多次访问之间保留。

常见问题

类似工具组合

做你这行的人, 还会一起用这些。

Made by Toolora · 100% client-side · Updated 2026-06-13