Skip to main content

Flutter JSON 序列化

· 4 min read
Alan

原文 - JSON 和序列化数据

因为Flutter中的dart不支持反射,所以没有类似 GSON/Jackson/Netonsoft.Net 那种类库,不支持反射的原因是为了支持 tree shake,减少App体积。

下面介绍如果使用json_serializable序列化:

安装依赖

flutter pub add json_annotation
flutter pub add build_runner --dev
flutter pub add json_model --dev # 用于从JSON文件生成dart类
flutter pub add json_serializable --dev

方式1 JSON文件生成实体类

json_model

使用步骤

根据JSON文件自动创建实体类

  1. 项目根目录创建 jsons 文件夹
  2. 创建JSON文件(文件内容示例参考下面)
  3. 执行命令生成 model: flutter pub run json_model src=jsons
jsons/user.json
{
"name":"wendux",
"father":"$user", //可以通过"$"符号引用其它model类, 这个是引用User类
"friends":"$[]user", // 可以通过"$[]"来引用数组
"keywords":"$[]String", // 同上
"age?": 20, // 年龄,可能为null
"license?": { // 该项目的开源许可证
"key": "mit",
"name": "MIT License",
"spdx_id": "MIT",
"url": "https://api.github.com/licenses/mit",
"node_id": "MDc6TGljZW5zZW1pdA=="
}
}

JSON文件特性

  • 可以通过 $ 符号引用其他model类, 比如引用 User类: "father": "$user"
  • 可以通过 $[] 引用输入, 比如 "array": "$[]User" 或者 "friends": "$[]String"
  • 可为空字段: "age?": 20
  • 使用 json_annotation中的所有注解, 比如:
{
"@JsonKey(name: '+1') int?": "loved", //将“+1”映射为“loved”
"name":"wendux",
"age?":20
}
  • 可以在JSON文件增加 @meta 信息定制dart类生成规则:
{
"@meta": {
"import": [ // 生成的Dart文件中需要额外import的文件,可以有多个
"test_dir/profile.dart"
],
"comments": { // Json文件中相应字段的注释
"name": "名字"
},
"nullable": true, // 是否生成的model字段都是可空的,如果为false,则字段为late
"ignore": false // json->dart时是否跳过当前文件,默认为false,设为true时,生成时则会跳过本json文件
},
"name":"wendux",
"age?":20
}

在实际ubuntu环境, 发现文件夹名必须是 Jsons. 自己根据实际情况调整.

方式2 手动编写实体类属性

手动编写实体类, 然后自动生成 fromJsontoJson 方法.

编写实体类

user.dart
import 'package:json_annotation/json_annotation.dart';

/// This allows the `User` class to access private members in
/// the generated file. The value for this is *.g.dart, where
/// the star denotes the source file name.
part 'user.g.dart';

/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
@JsonSerializable()
class User {
User(this.name, this.email, this.age);

String name;
String email;
@JsonKey(defaultValue: 18)
int age;

/// A necessary factory constructor for creating a new User instance
/// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
/// The constructor is named after the source class, in this case, User.
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

/// `toJson` is the convention for a class to declare support for serialization
/// to JSON. The implementation simply calls the private, generated
/// helper method `_$UserToJson`.
Map<String, dynamic> toJson() => _$UserToJson(this);
}
info

如果有嵌套类,比如 User.dart 有个字段 final Address address;,这个Address是个类,那就需要把 User 类的注解 @JsonSerializable() 改成 @JsonSerializable(explicitToJson: true).

执行命令生成

flutter pub run build_runner build # 执行该命令生成缺失的方法
flutter pub run build_runner watch # 或者执行该命令监听文件变化自动生成