当我们去请求网络数据接口或者缓存某些结构数据时,一般都会用到 JSON 数据交换格式。JSON在移动端、后端、前端中应用都非常广泛。在 Flutter 中 JSON 格式的解析使用 dart:convert 里的函数类进行编解码处理。
我们看一个最简单的编解码使用的例子:
// JSON解码
// 定义一个JSON格式字符串
String _jsonString = '{"name": "Flutter Book","author": "Google"}';
// 使用json.decode进行解码
Map<String, dynamic> book = json.decode(_jsonString);
// 解码后调用获取值
Column(
children: <Widget>[
Text('Book Name:${book['name']}'),
Text('Book Author:${book['author']}'),
],
));
// 再看下JSON编码
// 使用json.encode将实体对象编码为JSON字符串
String _bookJson = json.encode(book);
怎么样,用起来是不是很简单,这些只是最简单的例子。实际开发中可能会遇到更加庞大、复杂嵌套的 JSON 结构。
// 如果是一个List集合的JSON字符串的话
String _jsonListString =
'[{"name": "Flutter Book","author": "Google"},{"name": "Dart Book","author": "Google"}]';
// 解码成List
List books = json.decode(_jsonListString);
// 调用取值
print(books[0]["name"]);
接下来我们优化一下我们的 JSON 编解码,让我们在使用的时候更加高效和方便。
我们首先定义一个实体类。
Book:
class Book {
final String name;
final String author;
Book(this.name, this.author);
Book.fromJson(Map<String, dynamic> json)
: name = json['name'],
author = json['author'];
Map<String, dynamic> toJson() => {
'name': name,
'author': author,
};
}
可以看到,实体类里新增了两个方法:fromJson 和 toJson。分别用于将 JSON 字符串解码为实体对象和将实体对象转为 JSON 字符串格式。
我们可以这样使用:
// 解析JSON字符串
Map<String, dynamic> bookMap = json.decode(_jsonString);
// 调用Book里的fromJson方法转换创建实体Book
var bookBean = Book.fromJson(bookMap);
// 使用
print(bookBean.name);
print(bookBean.author);
// 编码JSON字符串
// 可以直接调用,推荐
String beanString = json.encode(bookBean);
// 或者调用实体类里的toJson方法即可,没必要,麻烦
String beanString = json.encode(bookBean.toJson());
这种写法扩展性更强、更高效、更安全。
在实际开发中,我们的实体对象可能属性很多,并且内部嵌套对象或 List 集合。那么类似这种更加复杂的对象,如果我们依然这样一个一个写方法、属性赋值、解析的话那将会非常耗费时间。在 Android 平台有 GsonFomat、Gson 这样的工具和库帮我们处理,在 Flutter 平台同样也有,Flutter 官方提供了一个插件库:json_serializable。
json_serializable 可以方便的帮助我们进行 JSON 自动序列化解码处理,免去很多重复的工作,也会避免出错。
插件库官方地址:
https://pub.dev/packages/json_serializable
接下来我们看下这个插件的简单用法.
首先我们需要在 pubspec.yaml 里添加依赖:
dependencies:
json_serializable: ^2.3.0
运行 flutter packages get 命令,或者在 Visual Studio 里更改了配置文件保存后就会自动同步相关资源。
这里建议 flutter sdk 使用最新的 1.5 版本(升级命令:flutter upgrade —force)。
之后,在使用的地方导包即可:
import 'package:json_serializable/json_serializable.dart';
接下来我们看下简单的用法:
// 我们新建一个实体类
import 'package:json_annotation/json_annotation.dart';
// book.g.dart 这个是配置自动生成的对应类的名字
part 'book.g.dart';
// JSON序列化注解
@JsonSerializable(nullable: false)
class Book{
Book(this.name, this.author);
String name;
String author;
factory Book.fromJson(Map<String, dynamic> json) => _$BookFromJson(json);
Map<String, dynamic> toJson() => _$BookToJson(this);
}
// 接下来配置自动生成命令
flutter packages pub run build_runner build
// 或者使用下面命令,每次新增修改实体类后都会自动监听生成
flutter packages pub run build_runner watch
// 执行完命令后,就会在同目录文件夹生成对应实体类
// book.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'book.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Book _$BookFromJson(Map<String, dynamic> json) {
return Book(json['name'] as String, json['author'] as String);
}
Map<String, dynamic> _$BookToJson(Book instance) =>
<String, dynamic>{'name': instance.name, 'author': instance.author};
// 会自动帮助我们去补充完成属性的映射工作
那么我们的 Book 这个类实际上就变成了 book.dart 和 book.g.dart 两部分组成的了。如果放在一起是这样的:
class Book{
Book(this.name, this.author);
String name;
String author;
Book _$BookFromJson(Map<String, dynamic> json) {
return Book(json['name'] as String, json['author'] as String);
}
Map<String, dynamic> _$BookToJson(Book instance) =>
<String, dynamic>{'name': instance.name, 'author': instance.author};
}
接下来看下使用,使用方式和前面没有区别:
// JSON字符串
String _jsonString = '{"name": "Flutter Book","author": "Google"}';
// 解码成实体类
Map<String, dynamic> bookMap = json.decode(_jsonString);
var bookBean = Book.fromJson(bookMap);
// 调用
print(bookBean.name);
print(bookBean.author);
// 将实体对象编码为JSON字符串
String beanString = json.encode(bookBean);
本节博客主要是给大家讲解了 Flutter 的 JSON 编解码的用法,内容很简单。