flutter的json转dart model问题
原文链接
Preface
最近在做一个app,以后续用来找工作可以拿出来看看。
试试自己到产品设计能力,前后端能力等等。
中间遇到到一些有值得记录的点全部记录在此。
Content
json - model
本地 json 与 model 互转,主要用到了
- json_serializiable
- json_annotation
- build_runner
meta版本依赖问题
由于使用的flutter版本是2.2.4,flutter_test与json_annotation同时依赖了不同版本的meta库,所以不得已,没有用上最新的json对应库:
json_annotation: ^4.0.1,
json_serializable: ^4.1.4
类型拓展
以下是模版,在原版对基础上新增了构造器参数,不然新版本会提醒 null safty 问题。
由于vs code老是提醒有错误,所以这个文件命名为template.tmpl。
import 'package:json_annotation/json_annotation.dart';
%t
part '%s.g.dart';
@JsonSerializable()
class %s {
%s(%c);
%s
factory %s.fromJson(Map<String,dynamic> json) => _$%sFromJson(json);
Map<String, dynamic> toJson() => _$%sToJson(this);
}
以下是生成model的dart程序,新增了构造器参数和复杂类型的支持:
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
const TAG = "\$";
const SRC = "./json"; //JSON 目录
const DIST = "lib/models/"; //输出model目录
void walk() {
//遍历JSON目录生成模板
var src = new Directory(SRC);
var list = src.listSync();
var template = new File("template/template.tmpl").readAsStringSync();
File file;
list.forEach((f) {
if (FileSystemEntity.isFileSync(f.path)) {
file = new File(f.path);
var paths = path.basename(f.path).split(".");
String name = paths.first;
if (paths.last.toLowerCase() != "json" || name.startsWith("_")) return;
if (name.startsWith("_")) return;
//下面生成模板
var map = json.decode(file.readAsStringSync());
//为了避免重复导入相同的包,我们用Set来保存生成的import语句。
var set = new Set<String>();
StringBuffer attrs = new StringBuffer();
List<String> params = [];
(map as Map<String, dynamic>).forEach((key, v) {
if (key.startsWith("_")) return;
attrs.write(getType(v, set, name));
attrs.write(" ");
attrs.write(key);
attrs.writeln(";");
attrs.write(" ");
params.add("required this.$key");
});
//新增的构造器参数部分
String conParams = "{${params.join(",")}}";
String className = name[0].toUpperCase() + name.substring(1);
var dist = format(template, [
name,
className,
className,
attrs.toString(),
className,
className,
className
]);
var _import = set.join(";\r\n");
_import += _import.isEmpty ? "" : ";";
dist = dist.replaceFirst("%t", _import);
dist = dist.replaceFirst("%c", conParams);
//将生成的模板输出
new File("$DIST$name.dart").writeAsStringSync(dist);
}
});
}
String changeFirstChar(String str, [bool upper = true]) {
return (upper ? str[0].toUpperCase() : str[0].toLowerCase()) +
str.substring(1);
}
//将JSON类型转为对应的dart类型
String getType(v, Set<String> set, String current) {
current = current.toLowerCase();
if (v is bool) {
return "bool";
} else if (v is int) {
return "int";
} else if (v is num) {
return "num";
} else if (v is Map) {
return "Map<String,dynamic>";
} else if (v is List) {
return "List";
} else if (v is String) {
//自定义类型的支持
if (v.startsWith("$TAG") && v.endsWith("$TAG")) {
return v.substring(1, v.length - 1);
}
//处理特殊标志
if (v.startsWith("$TAG[]")) {
var className = changeFirstChar(v.substring(3), false);
if (className.toLowerCase() != current) {
set.add('import "$className.dart"');
}
return "List<${changeFirstChar(className)}>";
} else if (v.startsWith(TAG)) {
var fileName = changeFirstChar(v.substring(1), false);
if (fileName.toLowerCase() != current) {
set.add('import "$fileName.dart"');
}
return changeFirstChar(fileName);
}
return "String";
} else {
return "String";
}
}
//替换模板占位符
String format(String fmt, List<Object> params) {
int matchIndex = 0;
String replace(Match m) {
if (matchIndex < params.length) {
switch (m[0]) {
case "%s":
return params[matchIndex++].toString();
}
} else {
throw new Exception("Missing parameter for string format");
}
throw new Exception("Invalid format string: " + m[0].toString());
}
return fmt.replaceAllMapped("%s", replace);
}
void main() {
walk();
}
生成脚本没有变动
dart ./lib/mo.dart
flutter packages pub run build_runner build --delete-conflicting-outputs
实际结果
普通类型
//record.json
{
"content":"拉屎",
"datetime":"$DateTime$",//复杂类型的传入方式
"cost":30,
"useful":true
}
生成结果:
import 'package:json_annotation/json_annotation.dart';
part 'record.g.dart';
@JsonSerializable()
class Record {
Record({required this.content,required this.datetime,required this.cost,required this.useful});
String content;
DateTime datetime;
int cost;
bool useful;
factory Record.fromJson(Map<String,dynamic> json) => _$RecordFromJson(json);
Map<String, dynamic> toJson() => _$RecordToJson(this);
}
嵌入类型
//mock.json
{
"version":1,
"targets":"$[]target",
"records":"$[]record",
"motivations":"$[]motivation"
}
生成结果
import 'package:json_annotation/json_annotation.dart';
import "target.dart";
import "record.dart";
import "motivation.dart";
part 'mock.g.dart';
@JsonSerializable()
class Mock {
Mock({required this.version,required this.targets,required this.records,required this.motivations});
int version;
List<Target> targets;
List<Record> records;
List<Motivation> motivations;
factory Mock.fromJson(Map<String,dynamic> json) => _$MockFromJson(json);
Map<String, dynamic> toJson() => _$MockToJson(this);
}
Reference
flutter的json转dart model问题的更多相关文章
- Flutter 使用json_model解析json生成dart文件
一.json_serializable使用步骤 1.集成json_serializable pubspec.yaml 添加以下依赖 dependencies: json_annotation: ^2. ...
- Flutter - JSON to Dart,一个json转dart实体的网站
如你所见,一个json转dart实体的网站,https://javiercbk.github.io/json_to_dart/
- flutter 解析json
关于flutter 解析json 自己看了几天,最近才大概知道是怎么个情况. 首先 要处理的 是后端返回的数据 ,如果是直接请求的话返回的是json 字符串 然后要把字符串转成对象,有几种方式参考 第 ...
- Flutter 中 JSON 解析
本文介绍一下Flutter中如何进行json数据的解析.在移动端开发中,请求服务端返回json数据并解析是一个很常见的使用场景.Android原生开发中,有GsonFormat这样的神器,一键生成Ja ...
- 将JSON字典转换为Model文件
将JSON字典转换为Model文件 1. 一切尽在不言中 2. 源码 https://github.com/YouXianMing/CreateModelFromJson 3. 说明 如果你还在手动写 ...
- iOS key value coding kvc在接收json数据与 model封装中的使用
iOS key value coding kvc在接收json数据与 model封装中的使用 使用 kvc 能够极大的简化代码工作,及以后的接口维护工作: 1:先创建MovieModel类.h和 . ...
- Swift Json解析与model互转
Json的解码与编码操作,这里使用swift自带的类JSONDecoder 和 JSONEncoder 1.基础处理 如果你的 JSON 数据结构和你使用的 Model 对象结构一致的话,那么解析过程 ...
- json转换成dart类 JSON to Dart
json_to_dart的使用 如果我们得到一个特别复杂的JSON,有时候会无从下手开始写Model,这时候就可以使用一些辅助工具.我认为json_to_dart是比较好用的一个.它可以直接把json ...
- 将json转化为model
/// <summary> /// 获取Json的Model /// </summary> /// <typeparam name="T">&l ...
- Flutter -------- 解析JSON数据
SON序列化方法: 手动序列化和反序列化通过代码生成自动序列化和反序列化 手动JSON序列化是指使使用dart:convert中内置的JSON解码器.它将原始JSON字符串传递给JSON.decode ...
随机推荐
- 使用React和Redux进行前端应用程序:现代Web应用程序框架
目录 标题:<27. 使用 React 和 Redux 进行前端应用程序:现代 Web 应用程序框架> 背景介绍: 随着现代 Web 应用程序的发展,前端开发人员需要一种高效的.灵活的框架 ...
- React SSG - 也写个 Demo 吧
上次写了一个 SSR 的 DEMO,今天写个小 Demo 来从头实现一下 react 的 SSG,来理解下 SSG 是如何实现的. 什么是 SSG SSG 即 Static Site Generati ...
- 解决redis从服务器未配置主服务器密码导致数据未同步&磁盘饱满问题
问题前置场景 本人前几天买了一台2核4G+40G磁盘空间的云服务器用来学习使用,在服务器上安装了docker.为了学习redis主从架构,使用docker-compose部署了一主二从三台redis服 ...
- 使用MASA Stack+.Net 从零开始搭建IoT平台 第五章 使用时序库存储上行数据
@ 目录 前言 分析 实施步骤 时序库的安装 解决playload没有时间戳问题 代码编写 测试 总结 前言 我们可以将设备上行数据存储到关系型数据库中,我们需要两张带有时间戳的表(最新数据表 和 历 ...
- 自己动手实现rpc框架(一) 实现点对点的rpc通信
自己动手实现rpc框架(一) 实现点对点的rpc通信 1. 什么是rpc? RPC是远过程调用(Remote Procedure Call)的缩写形式,其区别于一个程序内部基本的过程调用(或者叫函数/ ...
- Java杂记————object.getClass()和object.class以及Java中的toString()方法的的区别
不说废话,直接上干货: (注意大小写:object为对象,Object为类) 1,object.getClass()它是Object类的实例方法,返回一个对象运行时的类的Class对象,换句话说,它返 ...
- 记一次.Net分布式事务死锁现象以及解决方法
在本文中,将介绍一次遇到的.Net分布式事务死锁现象以及解决方法.我们将首先了解事务框架的构成,然后分析导致死锁的代码,最后提出解决方法. 事务框架 本次开发框架JMSFramework将分布式事务划 ...
- OSS的使用(谷粒商城58-64)
OSS的使用(谷粒商城58-64) 购买之类的就不在这里详述了,阿里云文档几乎都写了 创建bucket 学习阶段,相对独特的点在于我们需要选择公共读 项目开发阶段,不能选择公共读了,要尽量选择私有(代 ...
- PostgreSQL 10 文档: PostgreSQL 客户端工具
PostgreSQL 客户端应用 这部份包含PostgreSQL客户端应用和工具的参考信息.不是所有这些命令都是通用工具,某些需要特殊权限.这些应用的共同特征是它们可以被运行在任何主机上,而不管数 ...
- Linux 压缩文件用法
# tar 命令:可以用来压缩或解压缩文件: # 压缩 tar -czvf filename.tar.gz files # 解压缩 tar -xzvf filename.tar.gz # gzip 命 ...