Flutter json 解析 json_serializable 的使用并自动创建模板
1。使用 json_serializable 的说明
1.集成 json_serializable
pubspec.yaml 添加以下依赖
dependencies:
json_annotation: ^2.0.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: ^2.0.0
复制代码
添加flutter包后记得运行 get
2。创建模板将你的json数据放在这里(点我)即可创建模板文件,如下:![Flutter json解析json_serializable使用及自动化生成模板]()
- 填写json数据
- 填写类名
- 复制或下载。创建文件
在项目根目录运行flutter packages pub run build_runner watch
,创建xxx.g.dart
4。解析和序列化
注意引导包Confutse'dart:convert';
///json转model
String jsonString = '{"name": "Tony","email": "tony@example.com"}'
Map userMap = json.decode(jsonString);
var user = User.fromJson(userMap);
///model转json字符串
String jsonEncode = json.encode(user);
print(jsonEncode);
复制代码
2.自动生成模板
上述过程需要每次在网站上生成一个json文件来转换为模板。接下来我们直接在本地生成,只需要编写user.json文件,然后运行命令即可。这样每次改变json结构时,都可以直接编辑json文件然后运行命令,并且可以将json结构保存在本地,方便查看。? 运行 pub run json_model (Dart VM 项目)或 flutter packages pub run json_model (在 Flutter 中)来创建 Dart 模型类。生成的文件默认在“lib/models”目录下
详细文档地址:github.com/flutterchin…
2.一个小优化
如上直接导入插件包非常方便,但是使用过程中出现了一个小问题:
- 创建的模板文件名称与json文件名称相同。如果文件名下划线为
_
时,创建的类名也有下划线,不过我习惯使用驼峰命名法 - 同上。当字段名称带有下划线
_
时,创建的字段也会带有下划线。是的,如果要使用驼峰式命名,需要手动添加@JsonKey(name: 'username')
- 自动解析数据类型只支持几种常见类型,如
bool num Map列表。
,如果是DateTime
或任何其他类型的字段,则只能解析为字符串。 - 创建的模板格式不完美,强迫症患者必须手动格式化
如果这对你来说不友好或者你有自己的写作习惯,那就自己动手吧。我按照自己的习惯改成了这样:
- 类名、字段名驼峰式命名
- 支持
DateTime
类型(以后可以添加其他支持)完整 hod : 不要使用json_model文件,自己动手- 在项目根目录下创建一个名为“jsons”的目录;
- 创建或复制Json文件到“jsons”目录下;
- 在项目根目录下创建将项目复制到目录
mo.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 = "import 'package:json_annotation/json_annotation.dart';\r\n%t\npart '%s.g.dart';\r\n\r\n@JsonSerializable()\r\nclass %s {\r\n %s();\r\n\r\n %sfactory %s.fromJson(Map<String, dynamic> json) => _\$%sFromJson(json);\r\n\r\n Map<String, dynamic> toJson() => _\$%sToJson(this);\r\n}\r\n"; 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(); (map as Map<String, dynamic>).forEach((key, v) { if (key.startsWith("_")) return; /// ############################# ///处理key包含"_"时,转为驼峰并加上@JsonKey(name="key") if (key.contains("_")) { attrs.write('@JsonKey(name: "$key")'); attrs.write("\r\n "); attrs.write(getType(v, set, name)); attrs.write(" "); attrs.write(changeToCamelCase(key, false)); attrs.writeln(";"); attrs.write("\r\n "); } else { attrs.write(getType(v, set, name)); attrs.write(" "); attrs.write(key); attrs.writeln(";"); attrs.write("\r\n "); } }); String className = ""; /// ############################# ///处理有"_"时class不是驼峰命名 if (name.contains("_")) { className = changeToCamelCase(name, true); } else { 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); //将生成的模板输出 new File("$DIST$name.dart").writeAsStringSync(dist); } }); } /// ############################# ///转为驼峰命名 ///big 是否大驼峰 String changeToCamelCase(String word, bool big) { if (word.contains("_")) { String result = ""; List<String> words = word.split("_"); for (var value in words) { result += (value[0].toUpperCase() + value.substring(1).toLowerCase()); } return big ? result : (result[0].toLowerCase() + result.substring(1)); } else { return big ? word[0].toUpperCase() + word.substring(1) : word[0].toLowerCase() + word.substring(1); } } 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 num) { return "num"; } else if (v is Map) { return "Map<String,dynamic>"; } else if (v is List) { return "List"; } else if (v is String) { /// ############################# ///添加DateTime类型 try { DateTime dateTime = DateTime.parse(v); if (dateTime != null) { return "DateTime"; } } catch (e) {} //处理特殊标志 if (v.startsWith("$TAG[]")) { var className = changeFirstChar(v.substring(3), false); if (className.toLowerCase() != current) { set.add('import "$className.dart"'); } /// ############################# /// 自定义model类型名字大驼峰命名 return "List<${changeToCamelCase(className, true)}>"; } else if (v.startsWith(TAG)) { var fileName = changeFirstChar(v.substring(1), false); if (fileName.toLowerCase() != current) { set.add('import "$fileName.dart"'); } /// ############################# /// 自定义model类型名字大驼峰命名 return changeToCamelCase(fileName, true); } 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(); } 复制代码
这里是创建模板的方法和模板,Json_model的前身,这里
包含“#的注释## ##########################" 为修改部分。如果您有自己的需求,可以自行修改。- 在项目根目录下创建
mo.sh
文件。内容如下:
#!/usr/bin/env bash dart mo.dart flutter packages pub run build_runner build --delete-conflicting-outputs 复制代码
这是一个脚本。将命令打包并一起运行
注意:如果还没有设置 dart 环境变量,则必须:(在 Mac 上)
vim ~/.bash_profile
- 添加 exporter path/flutter/bin/cache /dart -sdk/bin:$PATH
source ~/. bash_profile
dart --version
正常显示版本号就可以了
- 设置好上面之后就只需要一步了。在项目根目录下运行
sh mo.sh
,ok,一切完美完成,让我给你看看结果重要参考:
www.jianshu.com/p/41210 …53/41210 book .flutterchina.club/chapter10/j…作者:天宇
链接:https://juejin.im/post/5d08a920e51d454f7230250b来源:et454f7230250b 版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。