Flutter的JSON和序列化

举报
yd_221104950 发表于 2020/11/28 23:42:06 2020/11/28
【摘要】 1.概述 许多移动或网页应用都使用 JSON 来处理类似与服务器交换数据的任务。Flutter中是禁止使用反射的。因此,Flutter中没有GSON或Jackson,在Flutter中是禁用的。因为这样的库需要使用运行时反射,而运行时反射会干扰Dart的_tree shaking_。 默认的JSON.decode是将一个json格式的string 转化成一个Map&...

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

  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

  
 
  • 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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。