许多移动或网页应用都使用 JSON 来处理类似与服务器交换数据的任务。Flutter中是禁止使用反射的。因此,Flutter中没有GSON或Jackson,在Flutter中是禁用的。因为这样的库需要使用运行时反射,而运行时反射会干扰Dart的_tree shaking_。
默认的JSON.decode是将一个json格式的string 转化成一个Map
官方推荐的使用Json的方式:
Map
,不转换成Object
。 对于一些小型项目,数据量不大的情况下是可以使用的,原生默认支持,只需要加入库dart:convert
。formJson(Map map)
和Map toJson()
这两个方法。package:json_serializable
进行转换。package:built_value
我们分别用这三种方式来处理以下这个JSON字符串:
{
"name": "John Smith",
"email": "[email protected]"
}
默认的JSON.decode是将一个json格式的string 转化成一个MapformJson(Map
和Map
这两个方法。
(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,
};
}
(2)利用dart:convert库,将JSON字符串转对象User:
import "dart:convert";// 导入dart:convert库
import 'User.dart';// 导入User类
void main(){
var jsonString = '''
{
"name":"Jhon Smith",
"email":"[email protected]"
}
''';
// Map,利用dart:convert将JSON字符串转成Map对象
var userMap = jsonDecode(jsonString);
print(userMap["name"]);
// 将map对象传到对象的fromJson方法里去设置属性值
var user = new User.fromJson(userMap);
print(user.email);
}
从JSON字符串转成对象是反序列化的过程,jsonDecode()
只能得Map对象,所以要写个fromJson来逐一给属性赋值。从对象转成JSON字符串这是一个序列化的过程,不需要调用我们写好的toJson()
,因为jsonEncode()
已经为我们做了。
print(jsonEncode(user));
输出结果:
{"name":"Jhon Smith","email":"[email protected]"}
package: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
(2)然后在项目根目录下执行pub get
命令,下载包:
~/IdeaProjects/MyDart$ /home/wongkyunban/dart-sdk/bin/pub get
(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);
}
(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
(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};
用外部包package:json_serializable
的方式与dart:dart:convert
的区别就在于前者Map对象转成实体类的代码是自动生成的,后者是手动。其实在Android studio安装一个插件flutter_json_format也可以很快生成这些代码,比使用外部包生成代码,更好管理,也更快。请参考《Android Studio的flutter_json_format插件使用》