pubspec.yaml 添加如下依賴html
dependencies:
json_annotation: ^2.0.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: ^2.0.0
複製代碼
添加完記得執行 flutter packages get
git
把你的json數據到這裏(點我)生成一下model文件 以下: github
在項目根目錄下執行flutter packages pub run build_runner watch
便可生成xxx.g.dartjson
注意導包import 'dart:convert';
vim
///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);
複製代碼
上述過程須要每次把json去生成網站去轉化成Model,接下來咱們直接在本地生成,只須要寫個user.json文件再執行下命令便可。這樣每次json結構有修改後能夠直接修改json文件再執行下命令便可,而且json結構能存在本地方便查看。bash
dev_dependencies:
json_model: ^0.0.2 #最新版本
複製代碼
具體文檔地址:github.com/flutterchin…app
上述方式直接導入插件包已經很方便了,但使用過程當中遇到了一點問題:優化
_
時生成的類名也是有下劃線的,但我習慣使用駝峯命名_
,生成的字段也是有下劃線的,要想使用駝峯命名須要手動在字段上方加上@JsonKey(name: 'user_name')
bool num Map List
等幾種常見類型,若是是DateTime
類型或其餘類型的字段只能解析成String。若是你感受這樣不友好或有本身的書寫習慣那麼就本身動手吧。我這裏按照本身的習慣改了一下:網站
DateTime
類型(後期有其餘支持能夠添加)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();
}
複製代碼
這裏是生成model的方法及模板,Json_model的前身,來自這裏
其中註釋包含 「#############################」的地方是修改過的地方,你們要有本身的需求能夠自行修改。ui
mo.sh
文件,內容以下:#!/usr/bin/env bash
dart mo.dart
flutter packages pub run build_runner build --delete-conflicting-outputs
複製代碼
這個是腳本,把命令打包後一塊兒執行
vim ~/.bash_profile
export PATH=your flutter path/flutter/bin/cache/dart-sdk/bin:$PATH
source ~/.bash_profile
dart --version
正常顯示版本號便可sh mo.sh
,ok,一切完美的搞定了,給你們看看結果