iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >怎么在Flutter上优雅地序列化一个对象
  • 112
分享到

怎么在Flutter上优雅地序列化一个对象

2023-06-04 08:06:18 112人浏览 八月长安
摘要

本文小编为大家详细介绍“怎么在Flutter上优雅地序列化一个对象”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么在Flutter上优雅地序列化一个对象”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。序列化一个

本文小编为大家详细介绍“怎么在Flutter上优雅地序列化一个对象”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么在Flutter上优雅地序列化一个对象”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

序列化一个对象才是正经事

对象的序列化反序列化是我们日常编码中一个非常基础的需求,尤其是对一个对象的JSON encode/decode操作。每一个平台都会有相关的库来帮助开发者方便得进行这两个操作,比如Java平台上赫赫有名的GSON,阿里巴巴开源的fastjson等等。

而在Flutter上,借助官方提供的JsonCodec,只能对primitive/Map/List这三种类型进行json的encode/decode操作,对于复杂类型,JsonCodec提供了receiver/toEncodable两个函数让使用者手动“打包”和“解包”。

显然,JsonCodec提供的功能看起来相当的原始,在闲鱼app中存在着大量复杂对象序列化需求,如果使用这个类,就会出现集体“带薪序列化”的盛况,而且还无法保证正确性。

官方推荐

机智如Google官方,当然不会坐视不理。json_serializable的出现就是官方给出的推荐,它借助dart Build System中的*buildrunner和json_annotation库,来自动生成fromJson/toJson函数内容。(关于使用build_runner*生成代码的原理,之前兴往同学的文章已经有所提及)

关于如何使用json_serializable网上已经有很多文章了,这里只简单提一些步骤:

  • Step 1 创建一个实体类。

  • Step 2 生成代码:

让build runner生成序列化代码。运行完成后文件夹下会出现一个xxx.g.dart文件,这个文件就是生成后的文件。

  • Step 3 代理实现:

把fromJson和toJson操作代理给上面生成出来的类。

我们为什么不用它实现?

json_serializable完美实现了需求,但它也有不满足需求的一面:

  • 使用起来有些繁琐,多引入了一个类

  • 很重要的一点是,大量的使用"as"会给性能和最终产物大小产生不小的影响。实际上闲鱼内部的《flutter编码规范》中,是不建议使用"as"的。(对包大小的影响可以参见三笠同学的文章,同时dart linter也对as的性能影响有所描述)

一种正经的方式

基于上面的分析,很明显的,需要一种新的方式来解决我们面临的问题,我们暂且叫它fish-serializable

1需要实现的功能

我们首先来梳理一下,一个序列化库需要用到:

  1. 获取可序列化对象的所有field以及它们的类型信息

  2. 能够构造出一个可序列化对象,并对它里面的fields赋值,且类型正确

  3. 支持自定义类型

  4. 最好能够解决泛型的问题,这会让使用更加方便

  5. 最好能够轻松得在不同的序列化/反序列化方式中切换,例如json和protobuf。

2困难在哪

  1. flutter禁用了dart:mirrors反射api无法使用,也就无法通过反射的方式new一个instance、扫描class的fields。

  2. 泛型的问题由于dart不进行类型擦出,可以获取,但泛型嵌套后依然无法解开。

3Let's rock

无法使用dart:mirrors是个“硬”问题,没有反射的支持,类的内容就是一个黑盒。于是我们在迈出第一步的时候就卡壳了- -!

这个时候笔者脑子里闪过了很多画面,白驹过隙,乌飞兔走,啊,不是...是c++,c++作为一种无法使用反射的语言,它是如何实现对象的 序列化/反序列化 操作的呢?

一顿搜索猛如虎之后,发现大神们使用创建类对象的回调函数配合宏的方式来实现c++中类似反射这样的操作。

这个时候,笔者又想到了曾经朝夕相处的Android(现在已经变成了flutter),Android中的Parcelable序列化协议就是一个很好的参照,它通过writeXXX APIs将类的数据写入一个中间存储进行序列化,再通过readXXX APIs进行反序列化,这就解决了我们上面提到的第一个问题,既如何将一个类的“黑盒子”打开。

同时,Parcelable协议中还需要使用者提供一个叫做Creator的静态内部类,用来在反序列化的时候反射创建一个该类的对象或对象数组,对于没有反射可用的我们来说,用c++的那种回调函数的方式就可以完美解决反序列化中对象创建的问题。

  • ValueHolder

  1. 这是一个数据中转存储的基类,它内部的writeXXX APIs提供展开类内部的fields的能力,而readXXX则

  2. 用来将ValueHolder中的内容读取赋值给类的fields。

  3. readList/readMap/readSerializable函数中的type argument,我们把它作为外部想要解释数据的

  4. 方式,比如readSerializable<T>(key: 'object'),表示外部想要把key为object的值解释为T类

  5. 型。

  • FishSerializable

FishSerializable是一个interface,creator是个一个get函数,用来返回一个“创建类对象的回调”,writeTo函数则用来在反序列化的时候放置ValueHoder->fields的代码。
  • JsonSerializer

它继承于FishSerializer接口,实现了encode/decode函数,并额外提供encodeToMap和decodeFromMap功能。JsonSerializer类似JsonCodec,直接面向使用者用来json encode/decode

以上,我们已经基本做好了一个flutter上支持对象序列化/反序列化操作的库的基本架构设计,对象的序列化过程可以简化为:

怎么在Flutter上优雅地序列化一个对象

由于ValueHolder中间存储的存在,我们可以很方便得切换 序列化/反序列器,比如现有的JsonSerializer用来实现json的encode/decode,如果有类似protobuf的需求,我们则可以使用ProtoBufSerializer来将ValueHolder中的内容转换成我们需要的格式。

困难是不存在的

1如何匹配类型

为了能支持泛型容器的解析,我们需要类似下面这样的逻辑:

  1. List<SerializableObject> list

  2.    = holder.readList<SerializableObject>(key: 'list');

  3. List<E> readList<E>({String key}){

  4.    List<dynamic> list = _read(key);

  5. }

  6. E _flattenList<E>(List<dynamic> list){

  7.    list?.map<E>((dynamic item){

  8.        // 比较E是否属于某个类型,然后进行对应类型的转换      

  9.    });

  10. }

在Java中,可以使用Class#isAssignableFrom,而在flutter中,我们没有发现类似功能的API提供。而且,如果做下面这个测试,你还会发现一些很有意思的细节:

  1. void main() {

  2.  print('int test');

  3.  test<int>(1);

  4.  print('\r\nint list test');

  5.  test<List<int>>(<int>[]);

  6.  print('\r\nobject test');

  7.  test<A<int>>(A<int>());

  8. }

  9. void test<T>(T t){

  10.  print(T);

  11.  print(t.runtimeType);

  12.  print(T == t.runtimeType);

  13.  print(identical(T, t.runtimeType));

  14. }

  15. class A<T>{

  16. }

输出的结果是:

怎么在Flutter上优雅地序列化一个对象

可以看到,对于List这样的容器类型,函数的type argument与instance的runtimeType无法比较,当然如果使用t is T,是可以返回正确的值的,但需要构造大量的对象。所以基本上,我们无法进行类型匹配然后做类型转换。

2如何解析泛型嵌套

接下去就是如何分解泛型容器嵌套的问题,考虑如下场景:

  1. Map<String, List<int>> listMap;

  2. listMap = holder.readMap<String, List<int>>(key: 'listMap');

readMap中得到的value type是一个 List<int>,而我们没有API去切割这个type argument。所以我们采用了一种比较“笨”也相对实用的方式。我们使用字符串切割了type argument,比如:

List<int> => <String>[List<int>, List, int]

然后在内部展开List或Map的时候,使用字符串匹配的方式匹配类型,在目前的使用中,完美得支持了标准List和Map容器互相嵌套。但目前无法支持标准List和Map之外的其他容器类型。

What's more

1IDE插件辅助

写过Android的Parcelable的同学应该有种很深刻的体会,Parcelable协议中有大量的“机械”代码需要写,类似设计的fish-serializable也一样。

为了不被老板和使用库的同学打死,同时开发了fish-serializable-intelij-plugin来自动生成这些“机械”代码。

2与json_serializable的对比

  • fish-serializable在使用上配合IDE插件,减少了大量的"as"操作符的使用,同时在步骤上也更加简短方便。

  • 相比于 json_annotation生成的代码, fish-serializable生成的代码也更具可读性,方便手动修改一些代码实现。

  • fish-serializable可以通过手动接管 序列化/反序列化 过程的方式完美兼容 json_annotation等其他方案。

读到这里,这篇“怎么在Flutter上优雅地序列化一个对象”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: 怎么在Flutter上优雅地序列化一个对象

本文链接: https://www.lsjlt.com/news/237010.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Flutter上优雅地序列化一个对象
    本文小编为大家详细介绍“怎么在Flutter上优雅地序列化一个对象”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么在Flutter上优雅地序列化一个对象”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。序列化一个...
    99+
    2023-06-04
  • 怎么优雅地打印一个Java对象
    本文小编为大家详细介绍“怎么优雅地打印一个Java对象”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么优雅地打印一个Java对象”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。提问者定义了这样一个类:publi...
    99+
    2023-06-16
  • python对象序列化怎么实现
    Python对象序列化可以通过pickle模块来实现。pickle模块提供了一种简单的持久化Python对象的方法,它将Python...
    99+
    2023-10-26
    python
  • Java对象序列化怎么实现
    本篇内容介绍了“Java对象序列化怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!从 Java 类产生 XML 把 Ajax 响应作为...
    99+
    2023-06-03
  • java中怎么降序排列一个对象数组
    你可以使用 `Arrays.sort()` 方法来对对象数组进行排序,然后使用 `Collections.reverse(...
    99+
    2023-10-11
    java
  • 怎么优雅地实现判断一个值是否在一个集合中
    本篇内容介绍了“怎么优雅地实现判断一个值是否在一个集合中”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!版本...
    99+
    2024-04-02
  • 在Python中怎么将类对象序列化为JSON
    本文小编为大家详细介绍“在Python中怎么将类对象序列化为JSON”,内容详细,步骤清晰,细节处理妥当,希望这篇“在Python中怎么将类对象序列化为JSON”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1. ...
    99+
    2023-06-29
  • 怎么在java里实例化一个对象
    要在Java中实例化一个对象,需要按照以下步骤进行操作:1. 创建一个类:首先,需要创建一个类来定义对象的属性和行为。类是描述对象的...
    99+
    2023-09-26
    java
  • Java中怎么实现对象的序列化和反序列化
    这篇文章给大家分享的是有关Java中怎么实现对象的序列化和反序列化的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。引言:序列化是将对象的状态信息转换为可以存储或传输的形式的过程,在...
    99+
    2024-04-02
  • json_encode()怎么转化一个对象
    小编给大家分享一下json_encode()怎么转化一个对象,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!初步测试我们需要新建一个具有多种属性的对象新建 ...
    99+
    2023-06-14
  • php怎么序列化数组和对象
    这篇文章主要讲解了“php怎么序列化数组和对象”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php怎么序列化数组和对象”吧!序列化是将对象的状态信息转换为可存储或传输的形式的过程。在序列化期...
    99+
    2023-06-20
  • 使用C#怎么对XML对象进行序列化和反序列化操作
    使用C#怎么对XML对象进行序列化和反序列化操作?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。public class XMLUtil{&n...
    99+
    2023-06-06
  • php怎么反序列化数组和对象
    这篇文章主要介绍了php怎么反序列化数组和对象,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。例子<php    $sites&n...
    99+
    2023-06-20
  • Java中的对象流和序列化怎么用
    本篇内容主要讲解“Java中的对象流和序列化怎么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java中的对象流和序列化怎么用”吧!       &nb...
    99+
    2023-06-02
  • 怎么用php反序列化数组和对象
    这篇文章主要讲解了“怎么用php反序列化数组和对象”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用php反序列化数组和对象”吧!1、unserialize()用于将通过 serializ...
    99+
    2023-06-20
  • C#中怎么实现JSON功能及对象的序列化和反序列化
    本篇内容主要讲解“C#中怎么实现JSON功能及对象的序列化和反序列化”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#中怎么实现JSON功能及对象的序列化和反序列化”吧!Newtonsoft.J...
    99+
    2023-06-03
  • json反序列化成任意对象怎么实现
    JSON反序列化成任意对象的实现可以通过以下步骤完成: 导入JSON模块:首先需要导入Python的`json`模块,该模块提供了...
    99+
    2023-10-27
    json
  • 怎么在java中创建一个对象
    这篇文章给大家介绍怎么在java中创建一个对象,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开发;4. 网页开发;5. ...
    99+
    2023-06-14
  • SpringBoot怎么整合Redis实现序列化存储Java对象
    今天小编给大家分享一下SpringBoot怎么整合Redis实现序列化存储Java对象的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解...
    99+
    2023-07-05
  • 怎么在java中创建一个对象数组
    这篇文章给大家介绍怎么在java中创建一个对象数组,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java的优点是什么1. 简单,只需理解基本的概念,就可以编写适合于各种情况的应用程序;2. 面向对象;3. 分布性,Ja...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作