Skip to content

JSON 序列化

Flutter 应用在与后端 API 交互时,需要将 JSON 字符串解析为 Dart 对象,以及将 Dart 对象序列化为 JSON 字符串。

手动解析

适合小型项目或数据结构简单的场景。

jsonDecode

dart
import 'dart:convert';

final jsonString = '{"name": "张三", "age": 25, "email": "zhang@example.com"}';

// 解析为 Map
final Map<String, dynamic> json = jsonDecode(jsonString);
print(json['name']);  // 张三

// 解析为 List
final jsonArray = '[1, 2, 3]';
final List<dynamic> list = jsonDecode(jsonArray);

手动创建 Model 类

dart
class User {
  final String name;
  final int age;
  final String email;

  User({required this.name, required this.age, required this.email});

  // 从 JSON Map 创建对象
  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      age: json['age'] as int,
      email: json['email'] as String,
    );
  }

  // 转换为 JSON Map
  Map<String, dynamic> toJson() {
    return {
      'name': name,
      'age': age,
      'email': email,
    };
  }
}

使用:

dart
// JSON → 对象
final jsonString = '{"name": "张三", "age": 25, "email": "zhang@example.com"}';
final json = jsonDecode(jsonString) as Map<String, dynamic>;
final user = User.fromJson(json);

// 对象 → JSON
final jsonMap = user.toJson();
final jsonString = jsonEncode(jsonMap);

嵌套对象

dart
class Address {
  final String city;
  final String street;

  Address({required this.city, required this.street});

  factory Address.fromJson(Map<String, dynamic> json) {
    return Address(
      city: json['city'] as String,
      street: json['street'] as String,
    );
  }

  Map<String, dynamic> toJson() => {'city': city, 'street': street};
}

class User {
  final String name;
  final Address address;  // 嵌套对象

  User({required this.name, required this.address});

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      address: Address.fromJson(json['address'] as Map<String, dynamic>),
    );
  }

  Map<String, dynamic> toJson() => {
    'name': name,
    'address': address.toJson(),
  };
}

代码生成(json_serializable)

手动编写 fromJsontoJson 代码量大且容易出错,json_serializable 可以自动生成这些代码。

安装

bash
flutter pub add json_annotation
flutter pub add dev:json_serializable
flutter pub add dev:build_runner

编写 Model

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

part 'user.g.dart';

@JsonSerializable()
class User {
  final String name;
  final int age;
  final String email;

  User({required this.name, required this.age, required this.email});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

生成代码

bash
# 一次性生成
dart run build_runner build

# 监听变化,自动重新生成(开发时推荐)
dart run build_runner watch

生成的 user.g.dart 文件包含 _$UserFromJson_$UserToJson 方法。

常用注解

dart
@JsonKey(name: 'user_name')   // JSON 中字段名与 Dart 属性名不同
final String userName;

@JsonKey(defaultValue: '')     // 默认值
final String nickname;

@JsonKey(ignore: true)          // 忽略该字段
final String internalId;

@JsonKey(fromJson: _fromJson)   // 自定义解析
final DateTime createdAt;

嵌套对象

dart
@JsonSerializable()
class Address {
  final String city;
  final String street;

  Address({required this.city, required this.street});

  factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json);
  Map<String, dynamic> toJson() => _$AddressToJson(this);
}

@JsonSerializable()
class User {
  final String name;
  final Address address;

  User({required this.name, required this.address});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

最佳实践

  1. 小型项目 / 快速原型:手动解析即可,减少依赖
  2. 正式项目:使用 json_serializable,减少手写错误
  3. API 响应统一处理
dart
// 通用 API 响应结构
class ApiResponse<T> {
  final int code;
  final String message;
  final T? data;

  ApiResponse({required this.code, required this.message, this.data});

  bool get isSuccess => code == 0;
}

// 使用
final response = await dio.get('/users/1');
final apiResponse = ApiResponse<Map<String, dynamic>>.fromJson(response.data);
if (apiResponse.isSuccess) {
  final user = User.fromJson(apiResponse.data!);
}
  1. 在 Isolate 中解析大 JSON:避免主线程卡顿
dart
import 'package:flutter/foundation.dart';

Future<Map<String, dynamic>> parseJsonInIsolate(String jsonString) async {
  return compute((String str) => jsonDecode(str) as Map<String, dynamic>, jsonString);
}

下一步

基于 Flutter 官方文档整理