Flutter 进阶:json 转 model 工具开发

一、需求来源

凡是用强类型语言进行开发工作的都免不了和模型打交道;就有一个不可或缺的需求:Json 字符串转成模型文件;

在做 iOS 原生开发时就基于 MacAPP 原生技术开发过自己的 swift 转模型工具 CoderHelper;可以生成 YYModel 和 HandyJSON 对应的定制模型文件,爽的一塌糊涂。

在开始接触 Flutter 开发之后,转模型都是用的网页版 json_to_dart,确实方便,但是作者不维护很久了,每次生成的模型文件一堆警告,都要一一处理,麻烦且不爽。且受制于人,我可是既要(方便)又要(高度自定义)也要(。。。)还要(。。。)的男人!

最终实现效果图:

二、实现需求

1、寻找开源支持

从零实现?怎么可能,我在 Flutter 开发可是不那么老的新手!

君子善假于物也

我可是站在巨人(开源社区)的肩上的男人。

既然 json_to_dart 作者不维护了,我维护行不行?追到 github 一看,网页版作者未开源。就此结束,怎么可能?f12 查看网页代码文件,发现有一个后缀为 dart 的文件和作者开源库 json_to_dart 非常类似,打开源码一看,确定找到目标库就是 json_to_dart。(早听说谷歌浏览器引擎可以解析 dart 文件,第一次见也是新鲜,多看了两眼。)

2、基于 json_to_dart 开发自己的工具

fork json_to_dart 克隆到本地,运行,果然生成的文件一堆黄色警告(我们开发用flutter 3.10.6)。接下来一顿修改,消灭所有警告,添加自己的定制代码(类前缀,后缀等等)。

一切搞定之后,核心功能已经实现了。但是岂能无衣?

3、开发一个操作界面,可以随意添加类名前后缀,根类名

顺手做成了响应式,可宽屏可竖屏(见效果图)。

原始 json

dart 复制代码
{
  "username": "javiercbk",
  "favouriteInteger": 18,
  "favouriteDouble": 1.618,
  "url": "https://api.github.com/users/javiercbk",
  "html_url": "https://github.com/javiercbk",
  "tags": ["dart", "json", "cool"],
  "randomIntegers": [1, 2, 3],
  "randomDoubles": [1.1, 2.2, 3.3],
  "personalInfo": {
    "firstName": "Javier",
    "lastName": "Lecuona",
    "location": "Buenos Aires, Argentina",
    "phones": [
      {
        "type": "work",
        "number": "123-this-is-a-fake-phone",
        "shouldCall": false
      },
      {
        "type": "home",
        "number": "123-this-is-a-phony-phone",
        "shouldCall": false
      }
    ]
  }
}

生成模型:

dart 复制代码
class YYRootModel {
  YYRootModel({
    this.username,
    this.favouriteInteger,
    this.favouriteDouble,
    this.url,
    this.htmlUrl,
    this.tags,
    this.randomIntegers,
    this.randomDoubles,
    this.personalInfo,
  });

  String? username;

  int? favouriteInteger;

  double? favouriteDouble;

  String? url;

  String? htmlUrl;

  List<String>? tags;

  List<int>? randomIntegers;

  List<double>? randomDoubles;

  PersonalInfo? personalInfo;

  YYRootModel.fromJson(Map<String, dynamic>? json) {
    if (json == null) {
      return;
    }
    username = json['username'];
    favouriteInteger = json['favouriteInteger'];
    favouriteDouble = json['favouriteDouble'];
    url = json['url'];
    htmlUrl = json['html_url'];
    tags = List<String>.from(json['tags'] ?? []);
    randomIntegers = List<int>.from(json['randomIntegers'] ?? []);
    randomDoubles = List<double>.from(json['randomDoubles'] ?? []);
    personalInfo = json['personalInfo'] != null
        ? PersonalInfo.fromJson(json['personalInfo'])
        : null;
  }

  Map<String, dynamic> toJson() {
    final map = <String, dynamic>{};
    map['username'] = username;
    map['favouriteInteger'] = favouriteInteger;
    map['favouriteDouble'] = favouriteDouble;
    map['url'] = url;
    map['html_url'] = htmlUrl;
    map['tags'] = tags;
    map['randomIntegers'] = randomIntegers;
    map['randomDoubles'] = randomDoubles;
    if (personalInfo != null) {
      map['personalInfo'] = personalInfo!.toJson();
    }
    return map;
  }
}

class YYPersonalInfoModel {
  YYPersonalInfoModel({
    this.firstName,
    this.lastName,
    this.location,
    this.phones,
  });

  String? firstName;

  String? lastName;

  String? location;

  List<Phones>? phones;

  YYPersonalInfoModel.fromJson(Map<String, dynamic>? json) {
    if (json == null) {
      return;
    }
    firstName = json['firstName'];
    lastName = json['lastName'];
    location = json['location'];
    if (json['phones'] != null) {
      final array = (json['phones'] as List).map((e) => Phones.fromJson(e));
      phones = List<Phones>.from(array);
    }
  }

  Map<String, dynamic> toJson() {
    final map = <String, dynamic>{};
    map['firstName'] = firstName;
    map['lastName'] = lastName;
    map['location'] = location;
    if (phones != null) {
      map['phones'] = phones!.map((v) => v.toJson()).toList();
    }
    return map;
  }
}

class YYPhonesModel {
  YYPhonesModel({
    this.type,
    this.number,
    this.shouldCall,
  });

  String? type;

  String? number;

  bool? shouldCall;

  YYPhonesModel.fromJson(Map<String, dynamic>? json) {
    if (json == null) {
      return;
    }
    type = json['type'];
    number = json['number'];
    shouldCall = json['shouldCall'];
  }

  Map<String, dynamic> toJson() {
    final map = <String, dynamic>{};
    map['type'] = type;
    map['number'] = number;
    map['shouldCall'] = shouldCall;
    return map;
  }
}

三、总结

1、工具已开发好了,工具类见 JsonToModelPage.dart
2、需要额外在类中添加自定义方法的可以二次 fork 我的 json_to_dart 进行二次开发。
3、作为开发者能把自己的部分工作自动化是一件非常酷的事情!最昂贵的是时间,省下来的都是大赚的。
相关推荐
潜意识起点9 分钟前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛13 分钟前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿23 分钟前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256563 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@3 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
F-2H6 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss7 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247559 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255029 小时前
前端常用算法集合
前端·算法