Flutter官方提供的Json轉Dart類的方案需要先手動寫一個Dart model類,然後通過build_runner和json_serializable包提供的相關命令和標註然後再自動生成toJson()
和fromJson
方法,這種方案最大問題在於需要開發者手動寫一個Model類。在一個專案中,我們需要的Model類可能非常多,如果都需要手動反覆去做的話會很麻煩、無味。為了解決這個問題,我們做了一個新的開發工具package Json_model, 使用它,可以只用一行命令,就能將Json檔案轉成Dart 類,我們再也不用手動去寫Dart類。
安裝
請參考Github文件。
使用
- 在工程根目錄下建立一個名為 "jsons" 的目錄;
- 建立或拷貝Json檔案到"jsons" 目錄中 ;
- 執行
pub run json_model
(Dart VM工程)orflutter packages pub run json_model
(Flutter中) 命令生成Dart model類,生成的檔案預設在"lib/models"目錄下
例子
Json檔案: jsons/user.json
{
"name":"wendux",
"father":"$user", //可以通過"$"符號引用其它model類
"friends":"$[]user", // 可以通過"$[]"來引用陣列
"keywords":"$[]String", // 同上
"age":20
}
複製程式碼
生成的Dart model類:
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
User();
String name;
User father;
List<User> friends;
List<String> keywords;
num age;
factory User.fromJson(Map<String,dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
複製程式碼
@JsonKey
您也可以使用json_annotation包中的“@JsonKey”標註特定的欄位。
這個功能在特定場景下非常有用,比如Json檔案中有一個欄位名為"+1",由於在轉成Dart類後,欄位名會被當做變數名,但是在Dart中變數名不能包含“+”,我們可以通過“@JsonKey”來對映變數名;
{
"@JsonKey(ignore: true) dynamic":"md",
"@JsonKey(name: '+1') int": "loved", //將“+1”對映為“loved”
"name":"wendux",
"age":20
}
複製程式碼
生成檔案如下:
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
User();
@JsonKey(name: '+1') int loved;
String name;
num age;
factory User.fromJson(Map<String,dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
複製程式碼
測試:
import 'models/index.dart';
void main() {
var u = User.fromJson({"name": "Jack", "age": 16, "+1": 20});
print(u.loved); // 20
}
複製程式碼
關於
@JsonKey
標註的詳細內容請參考json_annotation 包;
@Import
另外,提供了一個@Import
指令,該指令可以在生成的Dart類中匯入指定的檔案:
{
"@import":"test_dir/profile.dart",
"@JsonKey(ignore: true) Profile":"profile",
"name":"wendux",
"age":20
}
複製程式碼
生成的Dart類:
import 'package:json_annotation/json_annotation.dart';
import 'test_dir/profile.dart'; // 指令生效
part 'user.g.dart';
@JsonSerializable()
class User {
User();
@JsonKey(ignore: true) Profile profile; //file
String name;
num age;
factory User.fromJson(Map<String,dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
複製程式碼
更完整的示例請移步這裡 .
命令引數
預設的源json檔案目錄為根目錄下名為 "json" 的目錄;可以通過 src
引數自定義源json檔案目錄,例如:
pub run json_model src=json_files
複製程式碼
預設的生成目錄為"lib/models",同樣也可以通過dist
引數來自定義輸出目錄:
pub run json_model src=json_files dist=data # 輸出目錄為 lib/data
複製程式碼
注意,dist會預設已lib為根目錄。
程式碼呼叫
如果您正在開發一個工具,想在程式碼中使用json_model,此時便不能通過命令列來呼叫json_model,這是你可以通過程式碼呼叫:
import 'package:json_model/json_model.dart';
void main() {
run(['src=jsons']); //run方法為json_model暴露的方法;
}
複製程式碼
和視覺化生成工具對比
也有一些IDE外掛提供了Json轉Dart類的功能,它們和Json_model相比:
- Json_model需要單獨維護一個存放Json檔案的資料夾,如果有改動,只需修改Json檔案便可重新生成Model類;而IDE外掛一般需要使用者手動將Json內容拷貝複製到一個輸入框中,這樣生成之後Json檔案沒有存檔的化,之後要改動就需要手動。
- Json_model可以手動指定某個欄位引用的其它Model類,可以避免生成重複的類;而IDE外掛一般會為每一個Json檔案中所有巢狀物件都單獨生成一個Model類,即使這些巢狀物件可能在其它Model類中已經生成過。
- Json_model 提供了命令列轉化方式,可以方便整合到CI等非UI環境的場景。
最後
如果覺得對您有用,歡迎Star,Github Json_model專案地址。