热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【dart学习】Dart之JSON

概述现在很难想象移动应用程序不需要与后台交互或者存储结构化数据。现在开发,数据传输方式基本都是用JSON,在Flutter中是没有GSONJacksonMoshi这些库,因为这

概述

  现在很难想象移动应用程序不需要与后台交互或者存储结构化数据。现在开发,数据传输方式基本都是用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": "[email protected]"}';
Map
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 [email protected]

  这样,可以获得我们想要的数据了,我觉得这种方法很实用又能简单理解,但是不幸的是,JSON.decode()仅返回一个Map,这意味着当直到运行才知道值的类型,这种方法会失去大部分静态类型语言特性:类型安全、自动补全和编译时异常。这样的话,代码变得非常容易出错,就好像上面我们访问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
json)
: name
= json['name'],
email
= json['email'];
Map
toJson() =>
{
'name': name,
'email': email,
};
}

调用如下:

import 'model/User.dart';//记得添加
....
//使用模型类反序列化
decodeModelJson(){
var data
= '{"name": "Knight","email": "[email protected]"}';
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
json){--->一开始爆红
return _$UserFromJson(json);
}

Map
toJson() { --->一开始爆红
return _$UserToJson(this);
}
}

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

 

 

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


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


2.3.反序列化

var data= '{"name": "Knight","email": "[email protected]"}';
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);

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


 



推荐阅读
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 本文详细解析了Java类加载系统的父子委托机制。在Java程序中,.java源代码文件编译后会生成对应的.class字节码文件,这些字节码文件需要通过类加载器(ClassLoader)进行加载。ClassLoader采用双亲委派模型,确保类的加载过程既高效又安全,避免了类的重复加载和潜在的安全风险。该机制在Java虚拟机中扮演着至关重要的角色,确保了类加载的一致性和可靠性。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • Flutter 2.* 路由管理详解
    本文详细介绍了 Flutter 2.* 中的路由管理机制,包括路由的基本概念、MaterialPageRoute 的使用、Navigator 的操作方法、路由传值、命名路由及其注册、路由钩子等。 ... [详细]
  • 实验九:使用SharedPreferences存储简单数据
    本实验旨在帮助学生理解和掌握使用SharedPreferences存储和读取简单数据的方法,包括程序参数和用户选项。 ... [详细]
  • 字节流(InputStream和OutputStream),字节流读写文件,字节流的缓冲区,字节缓冲流
    字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 本文将详细介绍如何注册码云账号、配置SSH公钥、安装必要的开发工具,并逐步讲解如何下载、编译 HarmonyOS 2.0 源码。通过本文,您将能够顺利完成 HarmonyOS 2.0 的环境搭建和源码编译。 ... [详细]
  • 本题探讨如何编写程序来计算一个数值的整数次方,涉及多种情况的处理。 ... [详细]
  • 开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤
    开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤 ... [详细]
  • 优化Vite 1.0至2.0升级过程中遇到的某些代码块过大问题解决方案
    本文详细探讨了在将项目从 Vite 1.0 升级到 2.0 的过程中,如何解决某些代码块过大的问题。通过具体的编码示例,文章提供了全面的解决方案,帮助开发者有效优化打包性能。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
author-avatar
郑云雪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有