Flutter JSON模型转换插件convert_json_model的使用

Flutter JSON模型转换插件convert_json_model的使用

安装

pubspec.yaml文件中添加以下依赖:

dependencies:
  convert_json_model: #最新版本
  build_runner: ^2.0.1
  json_annotation: ^4.0.1
  json_serializable: ^4.1.1

安装这些依赖可以通过运行pub get命令或者通过Dart VSCode/Android Studio的安装选项。

什么?为什么?怎么用?

什么

这是一个命令行工具,用于将.json文件转换为.dart模型文件,并最终生成.g.dart文件(使用json_serializable)。

为什么

问题

你可能有一个系统或后端REST应用程序,并且想要构建一个Dart应用。你可能开始创建数据模型。但是将Dart Map转换为其他格式需要额外的工作,因此你可以使用json_serializable,但仍然需要手动逐个输入模型。如果你有一个巨大的系统,需要大量的模型,那么编写所有的模型可能会让你感到压力。

解决方案

这个命令行工具可以让现有的.json文件转换为Dart(json_serializable)文件。

为什么不直接使用现有的命令行库json_model

json_model非常棒,结构也很酷,但它不支持递归导入,这是我想要的功能。我还希望它能自动将变量名转换为驼峰命名法。我可以写一个issue并提交PR,但由于其代码结构不够清晰且可扩展性较差,而且我还看不懂它的注释,最后活跃在这个仓库的贡献者是在六月,我认为我不应该再等待了,所以我创建了一个新的工具。一些核心功能保持不变,但(也许)有更好的结构。

怎么做

它会遍历你的JSON文件,查找可能的类型、变量名、导入URI、装饰器和类名,并将其写入模板。 在项目根目录下创建/复制.json文件到./jsons/目录(默认),然后运行pub run convert_json_model

示例

{
  "id": 2,
  "title": "Hello Guys!",
  "content": "$content",
  "tags": "$[]tag",
  "user_type": "[@enum](/user/enum):admin,app_user,normal",
  "auth_state": "[@enum](/user/enum):verified(2),authenticated(1),guest(0)",
  "user": "$../user/user",
  "published": true
}

命令

pub run convert_json_model

或者

flutter pub run convert_json_model

输出

import 'package:json_annotation/json_annotation.dart';
import 'content.dart';
import 'tag.dart';
import '../user/user.dart';

part 'examples.g.dart';

[@JsonSerializable](/user/JsonSerializable)()
class Examples {
      Examples();

  int id;
  String title;
  Content content;
  List<Tag> tags;
  ExamplesUserTypeEnum 
    get examplesUserTypeEnum => _examplesUserTypeEnumValues.map[userType];
    set examplesUserTypeEnum(ExamplesUserTypeEnum value) => userType = _examplesUserTypeEnumValues.reverse[value];
  [@JsonKey](/user/JsonKey)(name: 'user_type') String userType;
  ExamplesAuthStateEnum 
    get examplesAuthStateEnum => _examplesAuthStateEnumValues.map[authState]!;
    set examplesAuthStateEnum(ExamplesAuthStateEnum value) => authState = _examplesAuthStateEnumValues.reverse[value];
  [@JsonKey](/user/JsonKey)(name: 'auth_state') int authState;
  User user;
  bool published;

  factory Examples.fromJson(Map<String,dynamic> json) => _$ExamplesFromJson(json);
  Map<String, dynamic> toJson() => _$ExamplesToJson(this);
}

enum ExamplesUserTypeEnum { Admin, AppUser, Normal }
enum ExamplesAuthStateEnum { Verified, Authenticated, Guest }

final _examplesUserTypeEnumValues = _ExamplesUserTypeEnumConverter({
  'admin': ExamplesUserTypeEnum.Admin,
  'app_user': ExamplesUserTypeEnum.AppUser,
  'normal': ExamplesUserTypeEnum.Normal,
});

final _examplesAuthStateEnumValues = _ExamplesAuthStateEnumConverter({
  2: ExamplesAuthStateEnum.Verified,
  1: ExamplesAuthStateEnum.Authenticated,
  0: ExamplesAuthStateEnum.Guest,
});

class _ExamplesUserTypeEnumConverter<String, O> {
  Map<String, O> map;
  Map<O, String>? reverseMap;

  _ExamplesUserTypeEnumConverter(this.map);

  Map<O, String> get reverse => reverseMap ??= map.map((k, v) => MapEntry(v, k));
}

class _ExamplesAuthStateEnumConverter<int, O> {
  Map<int, O> map;
  Map<O, int>? reverseMap;

  _ExamplesAuthStateEnumConverter(this.map);

  Map<O, int> get reverse => reverseMap ??= map.map((k, v) => MapEntry(v, k));
}

开始使用

  1. 在项目的根目录下创建一个名为jsons的目录(默认)。
  2. 将所有或创建的json文件放入jsons目录。
  3. 运行pub run convert_json_model。如果是Flutter项目,可以使用flutter packages pub run convert_json_model

使用方法

该包将读取.json文件,并生成.dart文件,将值的类型作为变量类型,并将作为变量名

描述 表达式 输入(示例) 输出(声明) 输出(导入)
声明类型取决于JSON值 {…: any type} {“id”: 1, “message”:“hello world”} int id;
String message;
-
导入模型并指定类型 {…: “$value”} {“auth”:"$user"} User auth; import ‘user.dart’
递归导入 {…: “$…/pathto/value”} {“price”:"$…/product/price"} Price price; import ‘…/product/price.dart’
指定类型列表并导入(也可以递归) {…: “$[]value”} {“addreses”:"$[]address"} List
addreses;
import ‘address.dart’
使用json_annotation [@JsonKey](/user/JsonKey) {…: “@JsonKey(…)”} {"@JsonKey(ignore: true) dynamic": “val”} @JsonKey(ignore: true) dynamic val; -
导入其他库(输入值可以是数组) {…: “@import”} {"@import":“package:otherlibrary/otherlibrary.dart”} - import ‘package:otherlibrary/otherlibrary.dart’
日期时间类型 {…: “@datetime”} {“createdAt”: “@datetime:2020-02-15T15:47:51.742Z”} DateTime createdAt; -
枚举类型 {…: “@enum:(folowed by enum separated by ‘,’)”} {"@import":"@enum:admin,app_user,normal"} enum UserTypeEnum { Admin, AppUser, Normal }(包含变量声明) -
枚举类型带值 {…: “@enum:(folowed by enum separated by ‘,’)”} {"@import":"@enum:admin(0),app_user(1),normal(2)"} enum UserTypeEnum { Admin, AppUser, Normal }(包含变量声明) -
独立编写代码(实验性) {…: “@_…”} {"@_ // any code here":",its like an escape to write your own code"} // any code here,its like an escape to write your own code -

示例

你可以复制以下JSON,并使用pub run convert_json_model命令生成。

基本示例

源文件

./jsons/user.json
{
  "id": 2,
  "username": "John Doe",
  "blocked": false
}

生成的文件

./lib/models/user.dart
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
[@JsonSerializable](/user/JsonSerializable)()
class User {
      User();

  int id;
  String username;
  bool blocked;

  factory User.fromJson(Map<String,dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

之后,json_serializable会自动生成.g.dart文件。

./lib/models/user.g.dart
part of 'user.dart';
User _$UserFromJson(Map<String, dynamic> json) {
  return User()
    ..id = json['id'] as int
    ..username = json['username'] as String
    ..blocked = json['blocked'] as bool;
}

Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
      'id': instance.id,
      'username': instance.username,
      'blocked': instance.blocked,
    };

指定类型变量

你可以使用$来指定变量的类型。

源文件

./jsons/user.json
{
  "id": 2,
  "username": "John Doe",
  "blocked": false,
  "addresses": "$address" // 前缀 $
}

在这种情况下,$address类似于告诉生成器导入address.dart并将标题大小写的Address作为变量addresses的类型。

生成的文件

./lib/models/user.dart
import 'package:json_annotation/json_annotation.dart';
import 'address.dart';  // 自动导入
part 'user.g.dart';

[@JsonSerializable](/user/JsonSerializable)()
class User {
  User();
  int id;
  String username;
  bool blocked;
  Address addresses;  // $address 转换为 Address 类型
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

指定列表类型变量

你可以使用$[]来指定变量的列表类型。

源文件

./jsons/user.json
{
  "id": 2,
  "username": "John Doe",
  "blocked": false,
  "addresses": "$[]address" // 前缀 $[]
}

生成的文件

./lib/models/user.dart
import 'package:json_annotation/json_annotation.dart';
import 'address.dart'; // 编写地址作为导入
part 'user.g.dart';

[@JsonSerializable](/user/JsonSerializable)()
class User {
  User();
  int id;
  String username;
  bool blocked;
  List<Address> addresses; // 列表类型
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

使用json_serializable [@JsonKey](/user/JsonKey)

你可以在key中使用[@JsonKey](/user/JsonKey)来指定[@JsonKey](/user/JsonKey)

源文件

./jsons/cart.json
{
  "[@JsonKey](/user/JsonKey)(ignore: true) dynamic": "md", // jsonKey别名
  "[@JsonKey](/user/JsonKey)(name: '+1') int": "loved", // jsonKey别名
  "name": "wendux",
  "age": 20
}

生成的文件

./lib/models/cart.dart
import 'package:json_annotation/json_annotation.dart';

part 'cart.g.dart';

[@JsonSerializable](/user/JsonSerializable)()
class Cart {
      Cart();

  [@JsonKey](/user/JsonKey)(ignore: true) dynamic md; // 生成jsonKey
  [@JsonKey](/user/JsonKey)(name: '+1') int loved; // 生成jsonKey
  String name;
  int age;

  factory Cart.fromJson(Map<String,dynamic> json) => _$CartFromJson(json);
  Map<String, dynamic> toJson() => _$CartToJson(this);
}

词汇表

实体

  • imports: 导入语句字符串。从.json文件中获取前缀为$的值,后缀为.dart并插入import '$import';\n
  • fileName: 文件名。从.json文件中获取前缀为$的值,但非单词字符(\W)被移除,并转换为驼峰命名法。
  • className: 类名。基本上是fileName,但转换为标题大小写。
  • declarations: 声明语句字符串。基本上是<a href="https://github.com/linlak/convert_json_model/blob/master/lib/core/dart_declaration.dart" rel="ugc">DartDeclaration</a>对象的列表,并转换为toString()
  • enums: 任何标记为[@enum](/user/enum)的语句将被解析并添加到生成的dart语句中。
  • enumConverters: 为了自动绑定枚举字符串值到实际枚举使用转换器。

模板

String defaultTemplate({
    imports,
    fileName,
    className,
    declarations,
    enums,
  }) =>  """
import 'package:json_annotation/json_annotation.dart';

$imports

part '$fileName.g.dart';

[@JsonSerializable](/user/JsonSerializable)()
class $className {
      $className();

  $declarations

  factory $className.fromJson(Map<String,dynamic> json) => _\$${className}FromJson(json);
  Map<String, dynamic> toJson() => _\$${className}ToJson(this);

}

$enums
""";

更多关于Flutter JSON模型转换插件convert_json_model的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter JSON模型转换插件convert_json_model的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


convert_json_model 是一个用于 Flutter 的代码生成插件,它可以根据 JSON 数据自动生成 Dart 数据模型类。这可以帮助开发者快速生成与 JSON 数据对应的 Dart 类,从而简化 JSON 数据的解析和序列化过程。

安装 convert_json_model

首先,你需要在 pubspec.yaml 文件中添加 convert_json_model 依赖项:

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  convert_json_model: ^0.0.1

然后运行 flutter pub get 来安装依赖。

使用 convert_json_model

  1. 创建 JSON 文件

    首先,你需要创建一个包含 JSON 数据的文件。例如,在 lib/models 目录下创建一个 user.json 文件:

    {
      "name": "John Doe",
      "age": 30,
      "email": "john.doe@example.com",
      "address": {
        "street": "123 Main St",
        "city": "Anytown"
      }
    }
    
  2. 运行代码生成器

    运行以下命令来生成 Dart 数据模型类:

    flutter pub run convert_json_model
    

    这将会根据 user.json 文件生成一个 user.dart 文件,内容如下:

    class User {
      final String name;
      final int age;
      final String email;
      final Address address;
    
      User({
        required this.name,
        required this.age,
        required this.email,
        required this.address,
      });
    
      factory User.fromJson(Map<String, dynamic> json) {
        return User(
          name: json['name'],
          age: json['age'],
          email: json['email'],
          address: Address.fromJson(json['address']),
        );
      }
    
      Map<String, dynamic> toJson() {
        return {
          'name': name,
          'age': age,
          'email': email,
          'address': address.toJson(),
        };
      }
    }
    
    class Address {
      final String street;
      final String city;
    
      Address({
        required this.street,
        required this.city,
      });
    
      factory Address.fromJson(Map<String, dynamic> json) {
        return Address(
          street: json['street'],
          city: json['city'],
        );
      }
    
      Map<String, dynamic> toJson() {
        return {
          'street': street,
          'city': city,
        };
      }
    }
    
  3. 使用生成的模型类

    现在你可以使用生成的 UserAddress 类来解析和序列化 JSON 数据。例如:

    import 'models/user.dart';
    
    void main() {
      final jsonString = '''
      {
        "name": "John Doe",
        "age": 30,
        "email": "john.doe@example.com",
        "address": {
          "street": "123 Main St",
          "city": "Anytown"
        }
      }
      ''';
    
      final Map<String, dynamic> userMap = jsonDecode(jsonString);
      final User user = User.fromJson(userMap);
    
      print('User Name: ${user.name}');
      print('User Address: ${user.address.street}, ${user.address.city}');
    
      final Map<String, dynamic> userJson = user.toJson();
      print('User JSON: $userJson');
    }
    

配置 convert_json_model

你可以在 build.yaml 文件中配置 convert_json_model 的行为。例如,指定输入目录和输出目录:

targets:
  $default:
    builders:
      convert_json_model|json_model:
        options:
          input_folder: "lib/models/json"
          output_folder: "lib/models"
回到顶部