概述

  现在很难想象移动应用程序不需要与后台交互或者存储结构化数据。现在开发,数据传输方式基本都是用JSON,在Flutter中是没有GSON/Jackson/Moshi这些库,因为这些库需要运行时反射,在Flutter是禁用的。运行时反射会干扰Dart的_tree shaking_。使用_tree shaking_,可以在发版是"去除"未使用的代码,来优化软件的大小。由于反射会默认使用所有代码,因此_tree shaking_会很难工作,这些工具无法知道哪些widget在运行时未被使用,因此冗余代码很难剥离,使用反射时,应用尺寸无法轻松进行优化,虽然不能在Flutter使用运行时反射,但有些库提供了类型简单易用的API,但它们是基于代码生成的。下面学学在Flutter中如何操作JSON数据的使用JSON有两个常规策略:

  1. 手动序列化和反序列化
  2. 通过代码生成自动序列化和反序列化 不同的项目有不同的复杂度和场景,针对于小的项目,使用代码生成器可能会杀猪用牛刀了。对于具有多个JSON model的复杂应用程序,手动序列化可能会比较繁琐,且容易出错。

1.手动序列化JSON

Flutter中基本的JSON序列化非常简单,Flutter有一个内置的dart:convert库,其中包含一个简单的JSON解码器和编码器。下面简单实现一下:

1.1.内连序列化JSON

首先记得导库:

import 'dart:convert';

然后根据字符串解析:

//内连序列化JSON
decodeJson() {
var data= '{"name": "Knight","email": "Knight@163.com"}';
Map<String,dynamic> user = json.decode(data);
//输出名字
print("Hello,my name is ${user['name']}");
//输出邮箱
print("Hello,This is my email ${user['email']}");
}

结果输出:

I/flutter ( 5866): Hello,my name is Knight
I/flutter ( 5866): Hello,This is my email Knight@163.com

  这样,可以获得我们想要的数据了,我觉得这种方法很实用又能简单理解,但是不幸的是,JSON.decode()仅返回一个Map<String,dynamci>,这意味着当直到运行才知道值的类型,这种方法会失去大部分静态类型语言特性:类型安全、自动补全和编译时异常。这样的话,代码变得非常容易出错,就好像上面我们访问name字段,打字打错了,达成namr。但是这个JSON在map结构中,编译器不知道这个错误的字段名(编译时不会报错)。为了解决所说的问题,模型类中序列化JSON的作用出来了。

1.2.模型类中序列化JSON

通过引入一个简单的模型类(model class)来解决前面提到的问题,建立一个User类,在类内部有两个方法:

  1. User.fromJson构造函数,用于从一个map构造出一个User实例map structure
  2. toJson方法,将User实例化一个map 这样调用的代码就具有类型安全、自动补全和编译时异常,当拼写错误或字段类型视为其他类型,程序不会通过编译,那就避免运行时崩溃。
1.2.1.user.dart

新建一个model文件夹,用来放实体,在其文件下新建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,
};
}

调用如下:

import 'model/User.dart';//记得添加
....
//使用模型类反序列化
decodeModelJson(){
var data= '{"name": "Knight","email": "Knight@163.com"}';
Map userMap = json.decode(data);
var user = new User.fromJson(userMap);
//打印出名字
print("Hello,my name is ${user.name}");
//打印出邮箱
print("Hello,my name is ${user.email}");
}

把序列化逻辑到移到模型本身内部,采用这种方法,反序列化数据就很简单了。序列化一个user,只是将User对象传递给该JSON.encode方法:

//序列化一个user
encodeModelJson(){
var user = new User("Knight","Knight163.com");
String user_json = json.encode(user);
print(user_json);
}

结果输出:

I/flutter ( 6684): {"name":"Knight","email":"Knight163.com"}

2.使用代码生产库序列化JSON

下面使用json_serializable package包,它是一个自动化的源代码生成器,可以为开发者生成JSON序列化魔板。

2.1.添加依赖

要包含json_serializable到项目中,需要一个常规和两个开发依赖项,开发依赖项是不包含在应用程序源代码中的依赖项:

dependencies:
# Your other regular dependencies here
json_annotation: ^2.0.0 dev_dependencies:-->开发依赖项
# Your other dev_dependencies here
build_runner: ^1.1.3 -->最新版本1.2.8 因为我sdk版本比较低 所以用低版本
json_serializable: ^2.0.2

2.2.代码生成

有两种运行代码生成器的方法:

  1. 一次性生成,在项目根目录运行flutter packages pub run build_runner build,可以在需要为我们的model生成json序列化代码。这触发一次性构建,它通过源文件,挑选相关的并为它们生成必要的序列化代码。这个非常方便,但是如果我们不需要每次在model类中进行更改都要手动运行构建命令的话会更好。
  2. 持续生成,使用_watcher_可以使源代码生成的过程更加方便,它会监视项目中文化的变化,并在需要时自动构建必要的文件,通过flutter packages pub run build_runner watch在项目根目录运行启动_watcher_,只需启动一次观察器,然后并让它在后台运行,这是安全的。

将上面的User.dart修改成下面:

import 'package:json_annotation/json_annotation.dart';
part 'User.g.dart';-->一开始爆红
//这个标注是告诉生成器,这个类是需要生成Model类的
@JsonSerializable()
class User{
User(this.name, this.email); String name;
String email; factory User.fromJson(Map<String, dynamic> json){--->一开始爆红
return _$UserFromJson(json);
} Map<String, dynamic> toJson() { --->一开始爆红
return _$UserToJson(this);
}
}

下面就用一次性生成命令,在项目根目录打开命令行执行:

最后发现会在当前目录生成User.g.dart文件:

里面的内容可以自己去看看看,就是反序列化/序列化的操作。注意:没生成User.g.dart执行多几次命令即可。最后通过json_serializable方式反序列化JSON字符串,不需要对先前代码修改:

2.3.反序列化

  var data= '{"name": "Knight","email": "Knight@163.com"}';
Map userMap = json.decode(data);
var user = new User.fromJson(userMap);
//打印出名字
print("Hello,my name is ${user.name}");
//打印出邮箱
print("Hello,my name is ${user.email}");

2.4.序列化

  var user = new User("Knight","Knight163.com");
String user_json = json.encode(user);
print(user_json);

结果是跟上面一样,不过这种方式额外多了生成一个文件...

【dart学习】-- Dart之JSON的更多相关文章

  1. 【dart学习】-- Dart之异步编程

    一,概述 编程中的代码执行,通常分为同步与异步两种. 同步:简单说,同步就是按照代码的编写顺序,从上到下依次执行,这也是最简单的我们最常接触的一种形式.但是同步代码的缺点也显而易见,如果其中某一行或几 ...

  2. [dart学习]第四篇:函数和操作符(本篇未完待续)

    接着学习dart的函数和操作符. 1.函数Function dart是一种真正的面向对象的语言,通常一个函数也是Function类型的对象,这也就是说可以把函数赋值给一个变量,或者作为另一个函数的入参 ...

  3. [dart学习]第二篇:dart变量介绍 (一)

    前言 本文的所有内容均是官方文档的简单翻译和理解,需要查看原文,请登录  https://www.dartlang.org/guides/language/language-tour  阅读, 让我们 ...

  4. Dart 学习资料

    Dart 学习资料: 学习资料 网址 Dart 编程语言中文网 http://dart.goodev.org/ Dart 官方包仓库 https://pub.dartlang.org/ 你想了解的Da ...

  5. [dart学习]第五篇:操作符

    前言:本系列内容假设读者有一定的编程基础,如了解C语言.python等. 本节一起来学习dart的操作符,直接拷贝官网的操作符描述表如下: Description Operator unary pos ...

  6. Dart学习笔记-运算符-条件表达式-类型转换

    Dart学习笔记-运算符-条件表达式-类型转换 一.运算符 1.算术运算符 + (加)- (减)* (乘)/ (除)~/ (取整) %(取余) 2.关系运算符 == (等等) != (不等) > ...

  7. Dart语言学习( 一) 为什么学习Dart?

    为什么学习Dart? Google及全球的其他开发者,使用 Dart 开发了一系列高质量. 关键的 iOS.Android 和 web 应用. Dart 非常适合移动和 web 应用的开发. 高效 D ...

  8. 简单易懂的Dart》 - Dart语言中文简明教程

    转自:https://www.blackglory.me/straightforward-dart/ Dart是Google公司发布的网络编程语言,其诞生的目的是为了让广大C类OOP程序员们克服Jav ...

  9. springmvc学习笔记(18)-json数据交互

    springmvc学习笔记(18)-json数据交互 标签: springmvc springmvc学习笔记18-json数据交互 springmvc进行json交互 环境准备 加入json转换的依赖 ...

随机推荐

  1. nofollow标签的作用 nofollow标签添加方法

    这篇文章主要介绍了nofollow标签的作用 nofollow标签添加方法,需要的朋友可以参考下   nofollow标签的作用 nofollow标签添加方法  模拟搜狗蜘蛛   nofollow标签 ...

  2. Invalid bound statement (not found)错误

    都对着,为什么会报这个错呢,mapper也拿到了,为什么查询时出错呢,最后看target里编译的文件发现少了mapping,xml没编译过去. 我的目录结构:dao层都编译过去了,但mapper.xm ...

  3. paper 149:Deep Learning 学习笔记(一)

     1. 直接上手篇 台湾李宏毅教授写的,<1天搞懂深度学习> slideshare的链接: http://www.slideshare.net/tw_dsconf/ss-62245351? ...

  4. flutter网格布局之GridView组件

    前面总结了使用ListView来实现列表,但是,有的时候,数据量很大,需要使用矩阵方式排列才能更清晰的展示数据,在flutter中,可以使用网格列表组件GridView来实现这个布局. GridVie ...

  5. fiddler使用笔记1

    转载地址:写得很不错的fildder教程   http://kb.cnblogs.com/page/130367/ Fiddler的基本介绍 Fiddler的官方网站:  www.fiddler2.c ...

  6. [CSP-S模拟测试]:蔬菜(二维莫队)

    题目描述 小$C$在家中开垦了一块菜地,可以抽象成一个$r\times c$大小的矩形区域,菜地的每个位置都种着一种蔬菜.秋天到了,小$C$家的菜地丰收了. 小$C$拟定了$q$种采摘蔬菜的计划,计划 ...

  7. 第七周编程总结&&实验报告五

    实验四 类的继承 实验目的 理解抽象类与接口的使用: 了解包的作用,掌握包的设计方法 实验要求 掌握使用抽象类的方法. 掌握使用系统接口的技术和创建自定义接口的方法. 了解 Java 系统包的结构. ...

  8. MySQL的limit分页性能测试加优化

    日常我们分页时会用到MySQL的limit字段去处理,那么使用limit时,有什么需要优化的地方吗?我们来做一个试验来看看limit的效率问题:环境:CentOS 6 & MySQL 5.71 ...

  9. 自动化测试常用断言的使用方法(python)-(转载@zhuquan0814

    自动化测试中寻找元素并进行操作,如果在元素好找的情况下,相信大家都可以较熟练地编写用例脚本了,但光进行操作可能还不够,有时候也需要对预期结果进行判断. 这里介绍几个常用断言的使用方法,可以一定程度上帮 ...

  10. servlet-获取web.xml配置的init-param参数

    1.web.xml配置的参数 <servlet> <servlet-name>firstServlet</servlet-name> <servlet-cla ...