Flutter的JSON和序列化
1.概述
许多移动或网页应用都使用 JSON 来处理类似与服务器交换数据的任务。Flutter中是禁止使用反射的。因此,Flutter中没有GSON或Jackson,在Flutter中是禁用的。因为这样的库需要使用运行时反射,而运行时反射会干扰Dart的_tree shaking_。
默认的JSON.decode是将一个json格式的string 转化成一个Map<String,dynamic>类型的Map, 是无法直接换成Object的。
官方推荐的使用Json的方式:
- 直接使用
Map
,不转换成Object
。 对于一些小型项目,数据量不大的情况下是可以使用的,原生默认支持,只需要加入库dart:convert
。 - 通过添加额外的方法来转换成Object。即给需要转换的类添加
formJson(Map<String,dynamic> map)
和Map<String,dynamic> toJson()
这两个方法。 - 使用外部包
package:json_serializable
进行转换。 - 使用外部包
package:built_value
我们分别用这三种方式来处理以下这个JSON字符串:
{
"name": "John Smith",
"email": "john@example.com"
}
- 1
- 2
- 3
- 4
1.使用 dart:convert手动序列化JSON
默认的JSON.decode是将一个json格式的string 转化成一个Map<String,dynamic>类型的Map, 是无法直接换成Object的。我们通过添加额外的方法来转换成Object。即给需要转换的类添加formJson(Map<String,dynamic> map)
和Map<String,dynamic> toJson()
这两个方法。
(1)定义实体User.dart:
class User {
final String name;
final String email; User(this.name, this.email); // 将Map键值对,赋给对象的属性
User.fromJson(Map<String, dynamic> json) : name = json["name"], email = json["email"];
// 将对象的属性转成JSON字符串
Map<String, dynamic> toJson() => { 'name': name, 'email': email, };
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
(2)利用dart:convert库,将JSON字符串转对象User:
import "dart:convert";// 导入dart:convert库
import 'User.dart';// 导入User类
void main(){
var jsonString = '''
{ "name":"Jhon Smith", "email":"jhonsmith@qq.com" }
''';
// Map<String, dynamic>,利用dart:convert将JSON字符串转成Map对象
var userMap = jsonDecode(jsonString);
print(userMap["name"]); // 将map对象传到对象的fromJson方法里去设置属性值
var user = new User.fromJson(userMap);
print(user.email);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
从JSON字符串转成对象是反序列化的过程,jsonDecode()
只能得Map对象,所以要写个fromJson来逐一给属性赋值。从对象转成JSON字符串这是一个序列化的过程,不需要调用我们写好的toJson()
,因为jsonEncode()
已经为我们做了。
print(jsonEncode(user));
- 1
输出结果:
{"name":"Jhon Smith","email":"jhonsmith@qq.com"}
- 1
2.使用外部包package:json_serializable
进行转换
2.1.使用外部包json_serializable
(1)引用包:pubspec.yaml
name: app
description: A new Dart project.
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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
(2)然后在项目根目录下执行pub get
命令,下载包:
~/IdeaProjects/MyDart$ /home/wongkyunban/dart-sdk/bin/pub get
- 1
(3)以json_serializable的方式编写实体: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<String,dynamic> json) => _$UserFromJson(json);
Map<String,dynamic> toJson() => _$UserToJson(this);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
(3)在项目根目录下,执行代码生成命令
- 一次性生成:
flutter packages pub run build_runner build
,这触发了一次性构建,它通过我们的源文件,挑选相关的并为它们生成必要的序列化代码。 - 持续生成
flutter packages pub run build_runner watch
这个命令会持续的监听所有被注解标记的文件并生成对应的文件。
运行完上面任意一个命令之后,没有异常的话会对应目录中生成对应的文件。之前的报红,就会正常。
~/AndroidStudioProjects/ME/startup_namer$ flutter packages pub run build_runner build
- 1
(4)执行代码生成命令后,源代码生成器创建一个名为User.g.dart文件:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'User.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
User _$UserFromJson(Map<String, dynamic> json) {
return User(json['name'] as String, json['email'] as String);
}
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{'name': instance.name, 'email': instance.email};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3.总结
用外部包package:json_serializable
的方式与dart:dart:convert
的区别就在于前者Map对象转成实体类的代码是自动生成的,后者是手动。其实在Android studio安装一个插件flutter_json_format也可以很快生成这些代码,比使用外部包生成代码,更好管理,也更快。请参考《Android Studio的flutter_json_format插件使用》
文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_40763897/article/details/108065745
- 点赞
- 收藏
- 关注作者
评论(0)