0
点赞
收藏
分享

微信扫一扫

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.使用 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,
};
}

(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);
}

从JSON字符串转成对象是反序列化的过程,​​jsonDecode()​​​只能得Map对象,所以要写个fromJson来逐一给属性赋值。从对象转成JSON字符串这是一个序列化的过程,不需要调用我们写好的​​toJson()​​​,因为​​jsonEncode()​​已经为我们做了。

print(jsonEncode(user));

输出结果:

{"name":"Jhon Smith","email":"jhonsmith@qq.com"}

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)然后在项目根目录下执行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)在项目根目录下,执行代码生成命令

  1. 一次性生成:​​flutter packages pub run build_runner build​​,这触发了一次性构建,它通过我们的源文件,挑选相关的并为它们生成必要的序列化代码。
  2. 持续生成​​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};

3.总结

用外部包​​package:json_serializable​​​的方式与​​dart:dart:convert​​​的区别就在于前者Map对象转成实体类的代码是自动生成的,后者是手动。其实在Android studio安装一个插件flutter_json_format也可以很快生成这些代码,比使用外部包生成代码,更好管理,也更快。请参考《Android Studio的flutter_json_format插件使用》


举报

相关推荐

0 条评论