Flutter - JSON与序列化

两种JSON序列化方式:

  • 手动序列化:适用小项目
  • 代码生成自动序列化:适用大中型项目

手动序列化

使用 dart:convert 中内置的JSON解码器。将原始JSON字符串传递给 jsonDecode() 方法,然后在 Map 结果中查找需要的值。

优点:简单,不需要其它依赖或特别设置。
缺点:手写序列化逻辑容易出错,当字段错误将会抛出异常。

//示例:user model 的 json
{
  "name": "John Smith",
  "email": "[email protected]"
}

通过dart:convert序列化的两种方式:

  1. 内联序列化JSON
    在 dart:convert 中,通过给 jsonDecode()方法传递JSON字符串参数来实现解码,但只能返回 Map ,这意味着直到运行时才知道值的类型,且失去了大部分静态语言特性:类型安全、自动补全和最重要的编译时异常。
Map user = jsonDecode(jsonString);

print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');
  1. 模板类型序列化JOSN
    通过引入模型类(model class)来解决前面提到的问题。
    示例: User model
    • User.fromJson() 构造函数:用于从 map 中构造 User 实例。
    • toJson() 方法:将 User 实例转化为 map。
//user.dart
class User {
  final String name;
  final String email;

  User(this.name, this.email);

  User.fromJson(Map json)
      : name = json['name'],
        email = json['email'];

  Map toJson() =>
    {
      'name': name,
      'email': email,
    };
}

//反序列化(decode)
Map userMap = jsonDecode(jsonString);
var user = new User.fromJson(userMap);

print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');

//序列化(encode)
String json = jsonEncode(user);

自动序列化

使用外部库生成序列化模板,通过初始化设置,运行从model类自动生成代码的文件观察器。
如:json_serializable 、 built_value

优点:字段错误,会在编译期捕获。
缺点:需要初始化设置。

示例:使用 json_serializable

  1. 添加依赖
    • dependencies:依赖
    • dev_dependencies 开发依赖:只在开发环境使用
//pubspec.yaml
dependencies:
  # Your other regular dependencies here
  json_annotation: ^2.0.0

dev_dependencies:
  # Your other dev_dependencies here
  build_runner: ^1.0.0
  json_serializable: ^2.0.0
  1. 以json_serializable的方式创建model类
//user.dart
import 'package:json_annotation/json_annotation.dart';

/// user.g.dart 将在运行生成命令后自动生成
part 'user.g.dart';

/// 该注解告诉代码生成器需要生成什么model
@JsonSerializable()

class User {
  User(this.name, this.email);

  String name;
  String email;

  /// 不同的类使用不同的mixin
  factory User.fromJson(Map json) => _$UserFromJson(json);

  Map toJson() => _$UserToJson(this);
}

//自定义字段名
@JsonKey(name: 'registration_date_millis')
final int registrationDateMillis;
  1. 运行代码生成
    第一次使用json_serializable创建类时可能会有如下错误:

    Flutter - JSON与序列化_第1张图片

    解决:通过代码生成器生成序列化模板,有两种方式:

    1. 一次性生成
      在项目根目录运行 flutter packages pub run build_runner build,会触发一次性构建 -- 检查筛选需要序列化的代码。
    2. 持续生成
      在项目根目录运行 flutter packages pub run build_runner watch 开启监视器(watcher),当项目文件变化时自动生成相应的文件。
  2. 使用

//decode
Map userMap = jsonDecode(jsonString);
var user = User.fromJson(userMap);

//encode
String json = jsonEncode(user);

没有有GSON / Jackson / Moshi

这些库使用了反射,而 Flutter中禁用反射
反射会干扰 tree shaking,在发版时 tree shaking 会“去除”未使用的代码,降低应用的大小。

虽然不能使用反射,但是一些基于代码生成的库,提供了类似的API。
详细参看:code generation libraries

你可能感兴趣的:(Flutter - JSON与序列化)