Flutter如何更便捷的json转model

5,326 阅读4分钟

0x1 前言

作为刚开始接触flutter的iOS开发,json转模型这部分一直是我非常头疼的地方。现在网上能找到的方案一般有两种

0x11 通过解析json创建模型文件

flutter里把反射直接禁掉了,这直接导致我们不能动态的给模型赋值。我们需要创建一个又一个的fromJson方法,然后在这个方法里取出一个又一个的数据赋值给模型。这是一部分重复且非常无聊代码。这种方式在使用的工程中也存在一系列的问题:

  • 不符合我们正常的开发习惯,一般我们拿到的都是接口字段定义,与之相对应的json文件我们是没有的,构建一个json文件这里又无端加了一部分工作量。
  • 没法对于数据做一些容错处理,在做旧业务迁移改造的时候这方面的问题会暴露出来,让人抓狂。
  • 后续添加删除字段比较麻烦

工具地址

0x12 json_serializable

json_serializable用到了dart里的注解来自动生成代码。关于注解你可以类比是编译插件,在预编译的时候解析出模型里定义的字段,然后根据这些字段创建与之相对应的fromJson方法。这种方式和上面的方案某些层面很相似,但是又在一定程度上解决了上面提到的一些问题:

  • 更加符合我们的开发习惯,根据接口字段定义属性。
  • 通过脚本生成代码,添加删除字段更加方便。

还存在的问题:

  • 还是没法对数据做容错处理。
  • 还是存在一些需要手动添加的重复代码,如下红框中的代码。

0x2 更加便捷的方案

我们先来梳理一下iOS里YYModel之类的框架是怎么做json自动转model的。首先通过runtime解析出定义的所有属性名、属性的类型。然后用这些属性名去json里取值赋值给model。那么我们如果想要做一套类似的库的话我们需要如下能力

0x21 解析出模型里所有属性名、属性类型

flutter把dart里的反射禁掉了,指望系统的api肯定是不现实了。我们比较容易想到的是我们可以手动输出这部分内容到一个全局的map里。要用的时候通过className去map里取。手动做肯定不现实,这部分的数据是有规律性的,所以通过脚本来做非常合适。你研究过json_serializable的实现的话你一定知道注解。我们可以用注解或者自定义builder来走一个预编译,在这个阶段我们能解析类,获取参数名、参数类型。解析出这部分数据之后创建一个文件,然后把这些解析出来的数据根据特定的格式输出一个全局的map到刚才创建的文件里。我这边不聊具体实现,只聊方案。具体注解相关的使用可以看注解相关资料

0x22 动态创建对象

通过上面的步骤我们能解析出属性的类型、属性名。对于自定义的对象来说,就会存在一个根据类名来创建对应对象的需求。通过闭包来创建对象,用className做key闭包做value,然后把这边分数据也放到上一步解析出来的map里。

className : () => className()

0x23 动态赋值

动态创建完对象之后我们需要能给这个对象的属性来动态赋值。和之前创建对象的处理方式类似,我们也可以通过闭包来做,我们输出如下格式的内容到上面的map中

name : (dynamic instance, value) => instance.name = value

0x24 动态取值

在做model to json功能的时候我们需要能够通过一个String格式的name去对象里动态获取这部分的数据。和上面用闭包来处理类似。我们需要输出如下格式的内容到之前的map中

name : (dynamic instance) => instaned.name

0x25 大致流程图

0x3 hn_easy_model

我这边已经实现了一套框架,配置完之后使用起来成本极低,对于客户端转过来写flutter的同学也更友好。框架地址,欢迎大家试用。