Flutter Dart Macro 宏简化 JSON 序列化

news2024/11/13 9:27:55

Flutter Dart Macro 宏简化 JSON 序列化

视频

https://youtu.be/gBZYjBmoOcU

https://www.bilibili.com/video/BV1tT421a7ev/

前言

原文 https://ducafecat.com/blog/using-dart-macros-to-simplify-json-serialization

今天我们将会体验 dart 语言新特性 macro 宏,来实现对 json 的序列化,用到的包是官方实验室写的 json 包。

本文将会一步步的带你实现这个功能,那我们开始吧。

Dart, 宏, JSON 序列化, 代码生成, 效率优化, 语言特性

参考

https://dart.dev/language/macros#view-the-generated-code

https://github.com/dart-lang/language/blob/main/working/macros/feature-specification.md

https://pub.dev/packages/json

macro 宏

好处

  • 直接语言集成。由于宏直接内置于语言中,它们比外部库提供更多的一致性并兼容语言的本机功能。
  • 减少外部依赖。通过使用宏来减少对外部库的依赖,您可以减小应用程序的大小并简化依赖管理。
  • 编译时代码生成。与运行时生成代码的解决方案相比,宏在编译时生成代码可能会提供更快的结果。
  • 增强定制化和自由度。开发者可以借助宏更好地根据项目独特需求定制代码生成,提供大量的定制自由度。

json_serializable 比较

为了在 Dart 中生成 JSON 序列化代码,这个库经常被使用,但它需要更多的依赖和设置。无需额外的工具,宏可以在源代码中自动生成 fromJson 和 toJson 方法。

freezed 比较

使用这个库,创建类型安全、不可变的 Dart 类变得非常简单。虽然 freezed 功能强大,但宏可能以更少的依赖和更直接的集成来完成类似的任务。

实现步骤

第一步:切到 dart 3.5 版本

https://docs.flutter.dev/release/archive?tab=macos

下载 beta channel , dart 3.5 版本。

我本机用的 fvm 管理多版本。

检查环境

❯ flutter --version

Flutter 3.23.0-0.1.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision 2feea7a407 (13 天前)2024-06-06 10:19:10 +0700
Engine • revision bb10c54666
Tools • Dart 3.5.0 (build 3.5.0-180.3.beta) • DevTools 2.36.0

第二步:配置 pubspec.yaml

pubspec.yaml

environment:
  sdk: ">=3.5.0-180.3.beta <4.0.0"
  
dependencies:
  json: ^0.20.2

官方实验室 json 包
https://pub.dev/packages/json

analysis_options.yaml

analyzer:
  enable-experiment:
    - macros

在编写代码时,除非你告诉分析器你正在试验此功能,否则它会发出警告。

第三步:编写测试代码

编写官方示例代码

lib/macros/user.dart

import 'package:json/json.dart';

() // Macro annotation.
class User {
  final int? age;
  final String name;
  final String username;
}

可以点击 Go to Augmentation 查看详细

augment library 'package:flutter_application_macro/macros/user.dart';

import 'dart:core' as prefix0;

augment class User {
  external User.fromJson(prefix0.Map<prefix0.String, prefix0.Object?> json);
  external prefix0.Map<prefix0.String, prefix0.Object?> toJson();
  augment User.fromJson(prefix0.Map<prefix0.String, prefix0.Object?> json, )
      : this.age = json[r'age'] as prefix0.int?,
        this.name = json[r'name'] as prefix0.String,
        this.username = json[r'username'] as prefix0.String;
  augment prefix0.Map<prefix0.String, prefix0.Object?> toJson() {
    final json = <prefix0.String, prefix0.Object?>{};
    if (this.age != null) {
      json[r'age'] = this.age!;
    }
    json[r'name'] = this.name;
    json[r'username'] = this.username;
    return json;
  }
}

这段代码自动的,不需要你编写。

启动时加入测试 lib/main.dart

class _MyHomePageState extends State<MyHomePage> {

  
  void initState() {
    super.initState();

    // Given some arbitrary JSON:
    final userJson = {
      'age': 5,
      'name': 'Roger',
      'username': 'roger1337',
    };

    // Use the generated members:
    final user = User.fromJson(userJson);
    print(user);
    print(user.toJson());
  }
  ...

如果代码成功运行将会打印 json 字符串

最后:运行测试

加入参数 --enable-experiment=macros 执行

我是 vsc 所以加在了 .vscode/launch.json

  "configurations": [
    {
      "name": "flutter_application_macro",
      "request": "launch",
      "type": "dart",
      "flutterMode": "debug",
      "program": "lib/main.dart",
      "args": ["--enable-experiment=macros"]
    },

主要是在 args 中加入 --enable-experiment=macros 参数

最后我们启动,查看输出信息。

Launching lib/main.dart on iPhone 15 in debug mode...
Xcode build done.                                           11.3s
Connecting to VM Service at ws://127.0.0.1:55696/aP-7aqbeIA4=/ws
Connected to the VM Service.
flutter: Instance of 'User'
flutter: {age: 5, name: Roger, username: roger1337}

官方 json 实现

https://pub.dev/packages/json

代码

https://github.com/dart-lang/sdk/blob/main/pkg/json/lib/json.dart

macro class JsonCodable
    with _Shared, _FromJson, _ToJson
    implements ClassDeclarationsMacro, ClassDefinitionMacro {
  const JsonCodable();

  /// Declares the `fromJson` constructor and `toJson` method, but does not
  /// implement them.
  
  Future<void> buildDeclarationsForClass(
      ClassDeclaration clazz, MemberDeclarationBuilder builder) async {
    final mapStringObject = await _setup(clazz, builder);

    await (
      _declareFromJson(clazz, builder, mapStringObject),
      _declareToJson(clazz, builder, mapStringObject),
    ).wait;
  }

  /// Provides the actual definitions of the `fromJson` constructor and `toJson`
  /// method, which were declared in the previous phase.
  
  Future<void> buildDefinitionForClass(
      ClassDeclaration clazz, TypeDefinitionBuilder builder) async {
    final introspectionData =
        await _SharedIntrospectionData.build(builder, clazz);

    await (
      _buildFromJson(clazz, builder, introspectionData),
      _buildToJson(clazz, builder, introspectionData),
    ).wait;
  }
}
  1. buildDeclarationsForClass 方法:
    • 在类声明阶段,为该类生成 fromJson 构造函数和 toJson 方法的声明。
  2. buildDefinitionForClass 方法:
    • 在类定义阶段,为 fromJsontoJson 提供具体的实现逻辑。
    • 该实现逻辑是根据类的属性信息自动生成的,通过反射获取类的结构信息。

代码

https://github.com/ducafecat/flutter_develop_tips/tree/main/flutter_application_macro_json

小结

这个 macro 实现的 json 目前也是试验产品,不建议你在项目中使用,本文的目的只是让你体验下宏的优势,和未来代码编写的一个趋势方向。

感谢阅读本文

如果有什么建议,请在评论中让我知道。我很乐意改进。


flutter 学习路径

  • Flutter 优秀插件推荐 https://flutter.ducafecat.com
  • Flutter 基础篇1 - Dart 语言学习 https://ducafecat.com/course/dart-learn
  • Flutter 基础篇2 - 快速上手 https://ducafecat.com/course/flutter-quickstart-learn
  • Flutter 实战1 - Getx Woo 电商APP https://ducafecat.com/course/flutter-woo
  • Flutter 实战2 - 上架指南 Apple Store、Google Play https://ducafecat.com/course/flutter-upload-apple-google
  • Flutter 基础篇3 - 仿微信朋友圈 https://ducafecat.com/course/flutter-wechat
  • Flutter 实战3 - 腾讯即时通讯 第一篇 https://ducafecat.com/course/flutter-tim
  • Flutter 实战4 - 腾讯即时通讯 第二篇 https://ducafecat.com/course/flutter-tim-s2

© 猫哥
ducafecat.com

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1937179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3中实现自然滚动表格列表,可调整滚动快慢

实现效果如图所示&#xff0c;可以调整滚动的快慢&#xff0c;可以实现内容高度不够的时候停止滚动的效果。 1.实现原理&#xff1a; 创建一个dom为ul&#xff0c;赋值为当前列表数据&#xff0c;然后拷贝这个dom赋值给第二个ul&#xff0c;然后判断屏幕高度跟滚动高度对比&a…

第三届智能机械与人机交互技术学术会议(IHCIT 2024)

【北航主办丨本届SPIE独立出版丨已确认ISSN号】 第三届智能机械与人机交互技术学术会议&#xff08;IHCIT 2024&#xff09; 2024 3rd International Conference on Intelligent Mechanical and Human-Computer Interaction Technology 2024年7月27日----中国杭州&#xff0…

Redis深度解析:从基础到高级特性,剖析关键技术

一、关于Redis Redis介绍 REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统&#xff0c;是跨平台的非关系型数据库。 Redis 是一个开源的使用 ANSIC 语言编写、遵守 BSD&#xff08;开源协议&#xff09; 协议、支持网络、可基于内存…

Linux云计算 |【第一阶段】ENGINEER-DAY5

主要内容&#xff1a; SELinux、系统故障修复、HTTPD/FTP服务搭建、防火墙策略管理、服务管理 一、SELinux安全制度 SELinux&#xff08;Security-Enhanced Linux&#xff09;&#xff0c;美国NSA国家安全局主导开发&#xff0c;一套增强Linux系统安全的强制访问控制体系&…

6. dolphinscheduler-3.0.0伪集群部署

环境说明&#xff1a; 主机名&#xff1a;cmc01为例 操作系统&#xff1a;centos7 安装部署软件版本部署方式centos7zookeeperzookeeper-3.4.10伪分布式hadoophadoop-3.1.3伪分布式hivehive-3.1.3-bin伪分布式clickhouse21.11.10.1-2单节点多实例dolphinscheduler3.0.0单节…

【JavaScript 算法】拓扑排序:有向无环图的应用

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现方法一&#xff1a;Kahn算法方法二&#xff1a;深度优先搜索&#xff08;DFS&#xff09;注释说明&#xff1a; 三、应用场景四、总结 拓扑排序&#xff08;Topological Sorting&#xff09;是一种…

测试数据科学家深度学习基础知识的 45 个问题(以及解决方案)

测试数据科学家深度学习基础知识的 45 个问题(以及解决方案) 一、介绍 早在2009年, 深度学习还只是一个新兴领域。只有少数人认为这是一个富有成效的研究领域。今天,它被用于开发应用程序,这些应用程序在一段时间前被认为是困难或不可能做到的。 语音识别、图像识别、在数…

<Qt> 初识Qt

目录 一、项目文件解析 widget.h main.cpp widget.cpp widget.ui .pro文件 二、QT 实现Hello World程序 &#xff08;一&#xff09;按钮控件 1. 纯代码 2. 图形化 &#xff08;二&#xff09;标签控件 1. 纯代码 2. 图形化 三、内存泄漏问题 四、qdebug()的使用…

MySQL(事务、索引)MyBatis

目录 事务 概述 四大特性&#xff08;ACID&#xff09; 索引 结构 语法 MyBatis 数据库连接池 lombok 基本操作--增删改查 根据主键删除 新增 更新 查询&#xff08;根据ID查询&#xff09; 查询&#xff08;条件查询&#xff09; XML映射文件 动态SQL 动态条…

Web安全:未验证的重定向和转发.

Web安全&#xff1a;未验证的重定向和转发. 未验证的重定向和转发漏洞是一种常见的Web安全漏洞&#xff0c;它允许攻击者将用户重定向到一个恶意的URL&#xff0c;而不是预期的安全URL。这种漏洞通常发生在应用程序处理重定向和转发请求时&#xff0c;未能对目标URL进行适当的…

RDMA 高性能架构基本原理与设计方案

在进行本文的学习学习之前&#xff0c;我们先对RDMA是什么做一个简单的科普与认识&#xff1a;一文带你了解什么是RDMA-CSDN博客 目录&#xff1a; 目录&#xff1a; 一、RDMA和传统网络方案的比较 1.1 传统网络方案&#xff1a; 1.1.1 缺点一&#xff1a;以太网卡&#xff0…

单机、集群、分布式服务器比较:

1. 单机服务器的瓶颈&#xff1a; 单机服务器&#xff1a;一台服务器独立运行一个工程所需的全部的业务模块 受限于服务器硬件资源&#xff0c;所承受用户并发量受限&#xff0c;32位linux操作系统最大并发量为两万任一模块的变动和修改&#xff0c;都会导致整个项目代码重新编…

移动端如何离线使用GPT

在移动端离线使用GPT&#xff0c;只需要一个app&#xff1a;H2O AI Personal GPT 是H2OAI上架的一款app&#xff0c;可离线使用&#xff0c;注重数据隐私&#xff0c;所有数据都只存储在本地。对H2OAI感兴趣的伙伴&#xff0c;可移步&#xff1a;https://h2o.ai 该app支持的模…

华为od 100问 持续分享6-入职体检

我是一名软件开发培训机构老师&#xff0c;我的学生已经有上百人通过了华为OD机试&#xff0c;学生们每次考完试&#xff0c;会把题目拿出来一起交流分享。 重要&#xff1a;2024年5月份开始&#xff0c;考的都是OD统一考试&#xff08;D卷&#xff09;&#xff0c;题库已经整…

如何学习Kafka:糙快猛的大数据之路(快速入门到实践)

在大数据开发的世界里,Kafka 无疑是一个不可或缺的重要角色。作为一个分布式流处理平台,它以其高吞吐量、可靠性和可扩展性而闻名。 目录 糙快猛学习法则Kafka 是什么?我的 Kafka 学习故事第一步: 快速上手第二步: 生产和消费消息第三步: 编写简单的生产者和消费者程序 深入Ka…

达梦数据库 DISQL连接数据库与执行SQL、脚本的方法

DISQL连接数据库与执行SQL、脚本的方法 1.DISQL介绍2.DISQL连接数据库的方法2.1 本地连接2.2 远程连接2.3 CONN连接 3.执行SQL、脚本的方法3.1 通过DISQL登录后在字符界面3.2 启动DISQL时运行脚本3.3 进入DISQL后&#xff0c;通过start命令运行脚本3.4 使用EDIT命令编辑脚本 1.…

(02)Unity使用在线AI大模型(调用Python)

目录 一、概要 二、改造Python代码 三、制作Unity场景 一、概要 查看本文需完成&#xff08;01&#xff09;Unity使用在线AI大模型&#xff08;使用百度千帆服务&#xff09;的阅读和实操&#xff0c;本文档接入指南的基础上使用Unity C#调用百度千帆大模型&#xff0c;需要…

【开发踩坑】使用PageHelper工具正常sql后面多无关语句

背景 SQL日志打印出现了脏东西&#xff1a; 本来结束的 where muc.code ?;后面凭空多出了一个 LIMIT语句 ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your …

【Spark On Hive】—— 基于电商数据分析的项目实战

文章目录 Spark On Hive 详解一、项目配置1. 创建工程2. 配置文件3. 工程目录 二、代码实现2.1 Class SparkFactory2.2 Object SparkFactory Spark On Hive 详解 本文基于Spark重构基于Hive的电商数据分析的项目需求&#xff0c;在重构的同时对Spark On Hive的全流程进行详细的…

Unity点击生成节点连线

Unity点击生成节点连线 效果 2.主要代码 Test_Line 控制类 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems;public class Test_Line : MonoBehaviour {public GameObject qiu_prefab;public List<Game…