原文链接

原文链接

Preface

最近在做一个app,以后续用来找工作可以拿出来看看。

试试自己到产品设计能力,前后端能力等等。

中间遇到到一些有值得记录的点全部记录在此。

Content

json - model

本地 jsonmodel 互转,主要用到了

  • 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);
}

以下是生成modeldart程序,新增了构造器参数和复杂类型的支持:

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问题的更多相关文章

  1. Flutter 使用json_model解析json生成dart文件

    一.json_serializable使用步骤 1.集成json_serializable pubspec.yaml 添加以下依赖 dependencies: json_annotation: ^2. ...

  2. Flutter - JSON to Dart,一个json转dart实体的网站

    如你所见,一个json转dart实体的网站,https://javiercbk.github.io/json_to_dart/

  3. flutter 解析json

    关于flutter 解析json 自己看了几天,最近才大概知道是怎么个情况. 首先 要处理的 是后端返回的数据 ,如果是直接请求的话返回的是json 字符串 然后要把字符串转成对象,有几种方式参考 第 ...

  4. Flutter 中 JSON 解析

    本文介绍一下Flutter中如何进行json数据的解析.在移动端开发中,请求服务端返回json数据并解析是一个很常见的使用场景.Android原生开发中,有GsonFormat这样的神器,一键生成Ja ...

  5. 将JSON字典转换为Model文件

    将JSON字典转换为Model文件 1. 一切尽在不言中 2. 源码 https://github.com/YouXianMing/CreateModelFromJson 3. 说明 如果你还在手动写 ...

  6. iOS key value coding kvc在接收json数据与 model封装中的使用

    iOS key value coding  kvc在接收json数据与 model封装中的使用 使用 kvc 能够极大的简化代码工作,及以后的接口维护工作: 1:先创建MovieModel类.h和 . ...

  7. Swift Json解析与model互转

    Json的解码与编码操作,这里使用swift自带的类JSONDecoder 和 JSONEncoder 1.基础处理 如果你的 JSON 数据结构和你使用的 Model 对象结构一致的话,那么解析过程 ...

  8. json转换成dart类 JSON to Dart

    json_to_dart的使用 如果我们得到一个特别复杂的JSON,有时候会无从下手开始写Model,这时候就可以使用一些辅助工具.我认为json_to_dart是比较好用的一个.它可以直接把json ...

  9. 将json转化为model

    /// <summary> /// 获取Json的Model /// </summary> /// <typeparam name="T">&l ...

  10. Flutter -------- 解析JSON数据

    SON序列化方法: 手动序列化和反序列化通过代码生成自动序列化和反序列化 手动JSON序列化是指使使用dart:convert中内置的JSON解码器.它将原始JSON字符串传递给JSON.decode ...

随机推荐

  1. C#设计模式19——装饰器模式的写法

    装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地给一个对象添加一些额外的职责,而不需要修改这个对象的代码. What(什么) 装饰器模式是一种结构型设计模式,它允许 ...

  2. 一分钟学一个 Linux 命令 - find 和 grep

    前言 大家好,我是 god23bin.欢迎来到<一分钟学一个 Linux 命令>系列,每天只需一分钟,记住一个 Linux 命令不成问题.今天需要你花两分钟时间来学习下,因为今天要介绍的是 ...

  3. docker-compose单服务器部署ELK

    docker-compose 部署ELK 本项目采用的ELK版本为6.5.3,7.0+ 以上的版本部分配置不适合,请查看docker-compose多服务器部署ELK文章 目录结构 elk |--do ...

  4. 2023-06-25:redis中什么是缓存穿透?该如何解决?

    2023-06-25:redis中什么是缓存穿透?该如何解决? 答案2023-06-25: 缓存穿透 缓存穿透指的是查询一个根本不存在的数据,在这种情况下,无论是缓存层还是存储层都无法命中.因此,每次 ...

  5. 【WALT】update_task_demand() 代码详解

    目录 [WALT]update_task_demand() 代码详解 代码展示 代码逻辑 用于判断是否进入新窗口的标志位 ⑴ 不累加任务运行时间的条件判断 ⑵ 仍在旧窗口中 ⑶ 进入新窗口 ⑷ 返回值 ...

  6. Unity的Console的控制类LogEntries:深入解析与实用案例

    使用Unity Console窗口的LogEntries私有类实现自定义日志系统 在Unity开发过程中,我们经常需要使用Console窗口来查看程序运行时的日志信息.Unity内置的日志系统提供了基 ...

  7. load initialize总结

    load initialize 方法的区别1.调用的方式 - load 根据函数地址调用 - initialize 通过objc_msgsend调用 2.调用时刻 - load runtime 加载类 ...

  8. Auto.Core

    Auto Core (基于AspectCore) 介绍 AutoCore是基于 .Net Standard 2.1用于简化 ASP.NET Core开发,AutoCore 在 AspectCore 的 ...

  9. 【技术积累】Vue.js中的事件【一】

    Vue中的事件是什么 在Vue.js中,事件是用于处理用户交互的重要机制.Vue.js提供了一系列的事件处理方法和指令,使开发者能够方便地处理用户的各种操作. 1. 事件绑定:Vue.js通过v-on ...

  10. React组件设计之性能优化篇

    我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:空山 前言 由于笔者最近在开发中遇到了一个重复渲染导致子组 ...