• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Flutter学习JSON 和序列化数据

武飞扬头像
留围冰
帮助1

1. 概述

Dart中没有类似于GSON/Jackson这种在Java编程中普遍使用的JSON处理工具,因为这样的库需要使用运行时进行 反射,这在 Flutter 中是被禁用的。

Dart中一般有两种JSON序列化和反序列化方式

  • 手动序列化数据
  • 利用代码生成进行自动序列化数据

一般,较小的项目使用手动序列化数据,中大型项目使用代码生成。
无论哪种方式,都需要在实体类中添加转换方法,其中从JSON转换为实体类的方法被定义为实体类的构造器,且方法名约定俗成地命名为fromJson;从实体类转换为JSON则是普通的方法,方法名常定义为toJsoon
下面的例子取自Flutter文档,该例子使用一个包含String nameString emailUser类及如下JSON字符串进行说明:

{
  "name": "John Smith",
  "email": "john@example.com"
}

2. 手动序列化数据

User类在user.dart文件中定义如下:

class User {
  final String name;
  final String email;

  User(this.name, this.email);

  User.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        email = json['email'];

  Map<String, dynamic> toJson() => {
        'name': name,
        'email': email,
      };
}

3. 利用代码生成进行自动序列化数据

尽管有其它库可以使用,但是这里使用json_serializable,一个自动化源代码生成器来用来生成 JSON 序列化数据模板。

3.1 添加json_serializable依赖

dependencies中添加json_annotationbuild_runner,在dev_dependencies中添加json_serializable,截止目前都是最新版本(可在此查看最新依赖版本)。
我的pubspec.yaml依赖部分如下:

environment:
  sdk: '>=2.19.0 <3.0.0'

dependencies:
 json_annotation: ^4.8.0
 build_runner: ^2.3.3

dev_dependencies:
  json_serializable: ^6.6.1

3.2 配置实体类文件

json_serializable会根据定义的实体类自动生成转换的代码,这部分代码单独放在一个名称为当前实体类文件后缀名为.g.dart的文件中(*.g.dart文件,*代表实体类文件名)。转换的方法名以_$开头,表示私有并自动生成,fromJson对应的方法名为_$BeanFromJsontoJson对应的方法名为_$BeanToJson,其中Bean代表实体类名称。*.g.dart文件会被作为实体类文件的一部分,被引用到实体类文件中用于实现fromJsontoJson方法,为此按如下步骤配置实体类:

  • user.dart文件中重新定义User
  • part的方式引入自动生成的文件user.g.dart,即part 'user.g.dart';
  • 在类上添加@JsonSerializable注解(为此需要import json_annotation包),且为了以正常格式输出嵌套类的数据,将注解的explicitToJson设置为true
  • 定义fromJson工厂构造器和toJson方法,直接使用胖箭头调用自动生成的转换方法,方法名为_$UserFromJson_$UserToJson与自动生成的方法名一致。
import 'package:json_annotation/json_annotation.dart';

part 'user.g.dart';

@JsonSerializable(explicitToJson: true)
class User {
  final String name;
  final String email;

  User(this.name, this.email);

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

  Map<String, dynamic> toJson() => _$UserToJson(this);
}

3.3 运行代码生成工具

配置好实体类文件后还不能直接使用,此时user.dart文件中的代码还会报错,因为这时候还没有生成user.g.dart文件。json_serializable提供了代码生成器来自动生成该文件,根据 json_serializable文档

  • 如果是Dart环境,可以在项目根目录下运行dart run build_runner build命令
  • 如果是Flutter环境,则在项目根目录下运行flutter pub run build_runner build命令

我的是Flutter环境,运行flutter pub run build_runner build命令后会在user.dart同目录下生成一个user.g.dart文件,文件内容如下:

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'user.dart';

// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************

User _$UserFromJson(Map<String, dynamic> json) => User(
      json['name'] as String,
      json['email'] as String,
    );

Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
      'name': instance.name,
      'email': instance.email,
    };

学新通

此时,user.dart中已经不会报错了。
上述代码生成器命令只会运行一次,如果我们修改了user.dart中的代码,则user.g.dart中的内容可能也需要随着修改,这样就需要重新运行一次命令,很不“智能”。为了实现“实时”监控文件变化从而自动重新生成.g.dart文件,json_serializable提供了监控命令:

flutter pub run build_runner watch

在项目根目录运行该命令后程序会持续监听文件变化,并且会在需要的时候自动构建必要的文件(但是可能会有延迟)。

4. 使用JSON

dart:convert包可以转换JSON数据:

  • 将字符串转换为JSON对象:jsonDecode(String source)
  • 将对象转换为字符串:jsonEncode(Object object)

测试代码如下:

import 'dart:convert';

void main() {
  // 假定有如下JSON格式的字符串
  String jsonString = """
  {
    "name": "John Smith",
    "email": "john@example.com"
  }
  """;

  // 首先将该字符串转换为JSON对象
  Map<String, dynamic> json = jsonDecode(jsonString);
  // 然后用JSON对象构造Dart对象
  User user = User.fromJson(json);
  // 反过来,再将Dart对象转为JSON对象
  Map<String, dynamic> json1 = user.toJson();
  // 当然也可以将对象序列化字符串
  String jsonString = jsonEncode(user);
  print(jsonString);
}
学新通

参考

[1] Flutter官方文档:JSON 和序列化数据

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcacaa
系列文章
更多 icon
同类精品
更多 icon
继续加载