惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LangChain Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
The Blog of Author Tim Ferriss
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Azure Blog
Microsoft Azure Blog
Microsoft Security Blog
Microsoft Security Blog
Stack Overflow Blog
Stack Overflow Blog
Webroot Blog
Webroot Blog
MongoDB | Blog
MongoDB | Blog
AI
AI
WordPress大学
WordPress大学
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Help Net Security
Help Net Security
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
J
Java Code Geeks
F
Fortinet All Blogs
The Cloudflare Blog
Cisco Talos Blog
Cisco Talos Blog
S
SegmentFault 最新的问题
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
M
MIT News - Artificial intelligence
The Hacker News
The Hacker News
G
GRAHAM CLULEY
H
Hacker News: Front Page
V
Vulnerabilities – Threatpost
L
Lohrmann on Cybersecurity
P
Privacy International News Feed
N
News and Events Feed by Topic
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Cyberwarzone
Cyberwarzone
T
Threatpost
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
S
Securelist
博客园 - 【当耐特】
MyScale Blog
MyScale Blog
Project Zero
Project Zero
Google DeepMind News
Google DeepMind News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Tailwind CSS Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
A
About on SuperTechFans
Simon Willison's Weblog
Simon Willison's Weblog

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
【Flutter 必备插件】JSON 序列化 - 少数派
2025-07-16 · via 少数派

在现代移动应用开发中,与服务器进行数据交互是必不可少的功能。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,因其易读性、简洁性和广泛支持性,已成为前后端通信的事实标准。在 Flutter 开发中,我们经常需要将 JSON 数据转换为 Dart 对象(反序列化),或将 Dart 对象转换为 JSON 数据(序列化)。

什么是 json_serializable

json_serializable 是一个基于Dart构建系统的代码生成库,它通过注解驱动的方式,自动为你的模型类生成序列化代码。它的核心优势在于:

  • 类型安全:生成的代码完全类型安全,避免了手动转换可能带来的类型错误
  • 减少样板代码:自动生成重复的序列化代码,提高开发效率
  • 可维护性:模型变更时,只需重新生成代码即可同步更新序列化逻辑
  • 灵活性:提供多种配置选项处理各种复杂场景

环境配置

dependencies:
  flutter:
    sdk: flutter
  json_annotation: ^4.9.0   # 提供必要的注解
 
dev_dependencies:
  build_runner: ^2.5.4      # 代码生成工具
  json_serializable: ^6.9.5 # 序列化代码生成器

实战

基本使用方法

1. 创建基础模型类

import 'package:json_annotation/json_annotation.dart';

// 这个文件是自动生成的,必须声明part
part 'token.g.dart';

// 核心注解,表示这个类需要生成序列化代码
@JsonSerializable()
class Token {
  final String accessToken;
  final int expiresIn;
  final String refreshToken;

  Token({required this.accessToken, required this.expiresIn, required this.refreshToken});

  /// 从 JSON 映射创建 Token 实例的工厂构造函数
  factory Token.fromJson(Map<String, dynamic> json) => _$TokenFromJson(json);

  /// 将 Token 实例转换为 JSON 映射的方法
  Map<String, dynamic> toJson() => _$TokenToJson(this);
}

关键点说明:

  1. part ‘token.g.dart’ 声明表示这个文件将包含自动生成的代码
  2. @JsonSerializable() 注解告诉生成器需要为这个类生成序列化代码
  3. _$TokenFromJson 和 _$UserToJson 是自动生成的函数,前缀 _$ 是生成器的命名约定
  4. 模型类应尽可能使用不可变字段(final),这符合函数式编程的最佳实践

2. 生成序列化代码

配置好模型类后,我们需要运行代码生成器。在项目根目录执行:

flutter pub run build_runner build

这个命令会:

  1. 扫描项目中所有被 @JsonSerializable() 注解的类
  2. 为每个类生成对应的 .g.dart 文件
  3. 生成的代码包含完整的序列化和反序列化实现

对于大型项目,推荐使用watch模式,它会监听文件变化并自动重新生成代码:

flutter pub run build_runner watch

高级配置与技巧

  1. 字段自定义配置

json_serializable 提供了丰富的配置选项,通过 @JsonKey 注解可以精细控制每个字段的序列化行为:

@JsonSerializable()
class AdvancedUser {
  @JsonKey(name: 'user_name') // 自定义JSON字段名
  final String name;
  
  @JsonKey(ignore: true) // 忽略此字段,不参与序列化
  final String? temporaryToken;
  
  @JsonKey(defaultValue: 'unknown') // 默认值
  final String status;
  
  @JsonKey(fromJson: _parseBalance, toJson: _stringifyBalance) // 自定义转换
  final double balance;
  
  @JsonKey(includeIfNull: false) // 为null时不包含在JSON中
  final String? nickname;
  
  AdvancedUser({
    required this.name,
    this.temporaryToken,
    this.status = 'unknown',
    required this.balance,
    this.nickname,
  });
  
  static double _parseBalance(String json) => double.parse(json);
  static String _stringifyBalance(double balance) => balance.toStringAsFixed(2);
  
  // ... fromJson/toJson方法
}
  1. 处理复杂嵌套结构

现实项目中的数据往往具有复杂的嵌套结构,json_serializable 可以优雅地处理这种情况:

@JsonSerializable()
class Address {
  final String street;
  final String city;
  final String zipCode;
  
  Address({required this.street, required this.city, required this.zipCode});
  
  factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json);
  Map<String, dynamic> toJson() => _$AddressToJson(this);
}
 
@JsonSerializable()
class Company {
  final String name;
  final Address address;
  
  Company({required this.name, required this.address});
  
  factory Company.fromJson(Map<String, dynamic> json) => _$CompanyFromJson(json);
  Map<String, dynamic> toJson() => _$CompanyToJson(this);
}
 
@JsonSerializable()
class Employee {
  final String id;
  final String name;
  final Company company;
  final List<String> skills; // 简单列表
  final List<Address> previousAddresses; // 复杂对象列表
  
  Employee({
    required this.id,
    required this.name,
    required this.company,
    required this.skills,
    required this.previousAddresses,
  });
  
  factory Employee.fromJson(Map<String, dynamic> json) => _$EmployeeFromJson(json);
  Map<String, dynamic> toJson() => _$EmployeeToJson(this);
}
  1. 枚举和泛型支持

json_serializable 对枚举和泛型也有很好的支持:

enum UserRole {
  @JsonValue('admin')
  admin,
  @JsonValue('editor')
  editor,
  @JsonValue('viewer')
  viewer,
  @JsonValue('guest')
  guest,
}
 
@JsonSerializable(genericArgumentFactories: true) // 启用泛型支持
class PaginatedResponse<T> {
  final int page;
  final int totalPages;
  final List<T> data;
  
  PaginatedResponse({
    required this.page,
    required this.totalPages,
    required this.data,
  });
  
  factory PaginatedResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json) fromJsonT,
  ) => _$PaginatedResponseFromJson(json, fromJsonT);
  
  Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
      _$PaginatedResponseToJson(this, toJsonT);
}
 
// 使用示例
final userResponse = PaginatedResponse<User>.fromJson(
  jsonMap,
  (json) => User.fromJson(json as Map<String, dynamic>),
);

性能优化

  1. 批量生成:一次性为所有模型生成代码,而不是频繁运行生成器
  2. 使用 freezed:结合 freezed 包可以生成不可变类,获得更好的性能和安全性
  3. 缓存结果:对于频繁访问的 JSON 数据,考虑在转换为对象后缓存结果
  4. 懒加载:对于大型 JSON 结构,考虑使用懒加载或分页技术

FQA

DateTime 类型的处理

@JsonKey(fromJson: _dateFromJson, toJson: _dateToJson)
final DateTime createdAt;
 
static DateTime _dateFromJson(String json) => DateTime.parse(json);
static String _dateToJson(DateTime date) => date.toIso8601String();

处理可能为 null 的字段

@JsonSerializable()
class Product {
  final String id;
  final String name;
  final String? description; // 可空字段
  
  Product({required this.id, required this.name, this.description});
  
  factory Product.fromJson(Map<String, dynamic> json) => _$ProductFromJson(json);
  Map<String, dynamic> toJson() => _$ProductToJson(this);
}