Flutter JSON5数据模型解析插件json5_model的使用

Flutter JSON5数据模型解析插件json5_model的使用

json5_model 是一个用于将JSON文件转换为Dart模型类的工具,支持解析嵌套的JSON和JSON5文件。它简化了从JSON生成Dart模型类的过程,并且可以轻松集成到Flutter项目的构建流程中。

安装

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

dev_dependencies:
  json_serializable: ^6.7.1
  json5_model: ^2.0.3

使用步骤

  1. 创建JSON目录:在项目根目录下创建一个名为 jsons 的目录。

    mkdir jsons
    
  2. 添加JSON文件:将需要解析的JSON文件放入 jsons 目录中。例如,创建一个 response.json 文件,内容如下:

    {
      "id": 1296269,
      "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
      "owner": {
        "login": "octocat"
      },
      "private": false,
      "topics": [
        "octocat",
        "atom",
        "electron",
        "api"
      ],
      "permissions": {
        "admin": false,
        "push": false,
        "pull": true
      },
      "security_and_analysis": {
        "advanced_security": {
          "status": "enabled"
        },
        "secret_scanning": {
          "status": "enabled"
        },
        "secret_scanning_push_protection": {
          "status": "disabled"
        }
      }
    }
    
  3. 生成Dart模型类:在终端中运行以下命令来生成Dart模型类。生成的文件将默认保存在 lib/models 目录下。

    flutter packages pub run json5_model
    

    如果你想自定义输入和输出目录,可以使用 --src--dist 参数。例如:

    flutter pub run json5_model --src=lib/data/json --dist=lib/data/model
    

示例代码

假设我们有一个 response.json 文件,内容如上所示。运行 flutter packages pub run json5_model 后,json5_model 会自动生成相应的Dart模型类。生成的代码如下:

import 'package:json_annotation/json_annotation.dart';

part 'github.g.dart';

@JsonSerializable(explicitToJson: true)
class Github {
  Github({
    required this.id,
    required this.nodeId,
    required this.owner,
    required this.private,
    required this.topics,
    required this.permissions,
    required this.securityAndAnalysis,
  });

  @JsonKey(name: "id", defaultValue: 0)
  int id;

  @JsonKey(name: "node_id", defaultValue: "")
  String nodeId;

  @JsonKey(name: "owner")
  Owner owner;

  @JsonKey(name: "private", defaultValue: false)
  bool private;

  @JsonKey(name: "topics", defaultValue: [])
  List<String> topics;

  @JsonKey(name: "permissions")
  Permissions permissions;

  @JsonKey(name: "security_and_analysis")
  SecurityAndAnalysis securityAndAnalysis;

  factory Github.fromJson(Map<String, dynamic> json) => _$GithubFromJson(json);

  Map<String, dynamic> toJson() => _$GithubToJson(this);
}

@JsonSerializable(explicitToJson: true)
class Owner {
  Owner({required this.login});

  @JsonKey(name: "login", defaultValue: "")
  String login;

  factory Owner.fromJson(Map<String, dynamic> json) => _$OwnerFromJson(json);

  Map<String, dynamic> toJson() => _$OwnerToJson(this);
}

@JsonSerializable(explicitToJson: true)
class Permissions {
  Permissions({
    required this.admin,
    required this.push,
    required this.pull,
  });

  @JsonKey(name: "admin", defaultValue: false)
  bool admin;

  @JsonKey(name: "push", defaultValue: false)
  bool push;

  @JsonKey(name: "pull", defaultValue: false)
  bool pull;

  factory Permissions.fromJson(Map<String, dynamic> json) => _$PermissionsFromJson(json);

  Map<String, dynamic> toJson() => _$PermissionsToJson(this);
}

@JsonSerializable(explicitToJson: true)
class AdvancedSecurity {
  AdvancedSecurity({required this.status});

  @JsonKey(name: "status", defaultValue: "")
  String status;

  factory AdvancedSecurity.fromJson(Map<String, dynamic> json) => _$AdvancedSecurityFromJson(json);

  Map<String, dynamic> toJson() => _$AdvancedSecurityToJson(this);
}

@JsonSerializable(explicitToJson: true)
class SecretScanning {
  SecretScanning({required this.status});

  @JsonKey(name: "status", defaultValue: "")
  String status;

  factory SecretScanning.fromJson(Map<String, dynamic> json) => _$SecretScanningFromJson(json);

  Map<String, dynamic> toJson() => _$SecretScanningToJson(this);
}

@JsonSerializable(explicitToJson: true)
class SecretScanningPushProtection {
  SecretScanningPushProtection({required this.status});

  @JsonKey(name: "status", defaultValue: "")
  String status;

  factory SecretScanningPushProtection.fromJson(Map<String, dynamic> json) => _$SecretScanningPushProtectionFromJson(json);

  Map<String, dynamic> toJson() => _$SecretScanningPushProtectionToJson(this);
}

@JsonSerializable(explicitToJson: true)
class SecurityAndAnalysis {
  SecurityAndAnalysis({
    required this.advancedSecurity,
    required this.secretScanning,
    required this.secretScanningPushProtection,
  });

  @JsonKey(name: "advanced_security")
  AdvancedSecurity advancedSecurity;

  @JsonKey(name: "secret_scanning")
  SecretScanning secretScanning;

  @JsonKey(name: "secret_scanning_push_protection")
  SecretScanningPushProtection secretScanningPushProtection;

  factory SecurityAndAnalysis.fromJson(Map<String, dynamic> json) => _$SecurityAndAnalysisFromJson(json);

  Map<String, dynamic> toJson() => _$SecurityAndAnalysisToJson(this);
}

避免覆盖

版本大于2.0.0的 json5_model 在成功转换后会自动将JSON文件重命名为以 _ 开头的文件名(例如 response.json 会被重命名为 _response.json),以便在重新执行自动生成功能时跳过这些文件。如果你不希望自动重命名,可以在命令中添加 --once=false 参数。

flutter pub run json5_model --once=false

全局命令参数

  • 源JSON文件目录:默认是项目根目录下的 jsons 文件夹。你可以通过 --src 参数自定义源文件夹路径。例如:

    flutter pub run json5_model --src=lib/data/json
    
  • 输出目录:默认是 lib/models 文件夹。你可以通过 --dist 参数自定义输出路径。例如:

    flutter pub run json5_model --src=lib/data/json --dist=lib/data/model
    

代码调用

如果你正在开发一个工具并希望在代码中使用 json5_model,可以通过代码调用 run 方法来生成模型类:

import 'package:json5_model/json5_model.dart';

void main() {
  run(['src=jsons']);  // 调用 json5_model 的 run 方法
}

运行示例

  1. 进入 example 目录:

    cd example
    
  2. 运行 json5_model

    flutter packages pub run json5_model
    
  3. 自定义输入和输出目录:

    flutter pub run json5_model --src=jsons --dist=lib/test/json
    

更多关于Flutter JSON5数据模型解析插件json5_model的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter JSON5数据模型解析插件json5_model的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,json5_model 是一个用于解析 JSON5 格式数据的插件。JSON5 是一种 JSON 的超集,它允许一些额外的语法,比如尾随逗号、注释等,使 JSON 数据更加易读和易写。下面是一个使用 json5_model 插件解析 JSON5 数据模型的示例代码。

首先,确保你已经在 pubspec.yaml 文件中添加了 json5_model 依赖:

dependencies:
  flutter:
    sdk: flutter
  json5_model: ^x.y.z  # 请将 x.y.z 替换为最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来,假设我们有一个 JSON5 数据模型,如下所示:

{
  name: "John Doe",  // JSON5 支持注释
  age: 30,
  email: "john.doe@example.com",
  // JSON5 支持尾随逗号
  address: {
    street: "123 Main St",
    city: "Anytown",
    zip: "12345",
  },
  phoneNumbers: [
    "555-1234",
    "555-5678"
  ]
}

我们将创建一个 Dart 数据类来表示这个 JSON5 数据模型,并使用 json5_model 插件进行解析。

  1. 创建一个 Dart 文件(例如 models/user.dart),并定义数据类:
import 'package:json5_model/json5_model.dart';

part 'user.json5.g.dart';

@Json5Serializable()
class User {
  String name;
  int age;
  String email;
  Address address;
  List<String> phoneNumbers;

  User({
    required this.name,
    required this.age,
    required this.email,
    required this.address,
    required this.phoneNumbers,
  });

  // 生成 JSON5 序列化方法
  factory User.fromJson5(Map<String, dynamic> json) => _$UserFromJson5(json);

  // 生成 JSON5 反序列化方法
  Map<String, dynamic> toJson5() => _$UserToJson5(this);
}

@Json5Serializable()
class Address {
  String street;
  String city;
  String zip;

  Address({
    required this.street,
    required this.city,
    required this.zip,
  });

  // 生成 JSON5 序列化方法
  factory Address.fromJson5(Map<String, dynamic> json) => _$AddressFromJson5(json);

  // 生成 JSON5 反序列化方法
  Map<String, dynamic> toJson5() => _$AddressToJson5(this);
}
  1. 在项目根目录下运行以下命令以生成 JSON5 序列化/反序列化代码:
flutter pub run build_runner build --build-filter=json5_model:.

这将在 models/ 目录下生成 user.json5.g.dart 文件,其中包含必要的序列化/反序列化逻辑。

  1. 现在,你可以在你的 Flutter 应用中使用这些类来解析 JSON5 数据:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'models/user.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('JSON5 Parsing Example'),
        ),
        body: Center(
          child: FutureBuilder<User>(
            future: fetchUser(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  User user = snapshot.data!;
                  return Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text('Name: ${user.name}'),
                      Text('Age: ${user.age}'),
                      Text('Email: ${user.email}'),
                      Text('Address: ${user.address.street}, ${user.address.city}, ${user.address.zip}'),
                      Text('Phone Numbers: ${user.phoneNumbers.join(", ")}'),
                    ],
                  );
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }

  Future<User> fetchUser() async {
    // 假设这是你的 JSON5 数据字符串
    String json5String = '''
    {
      name: "John Doe",
      age: 30,
      email: "john.doe@example.com",
      address: {
        street: "123 Main St",
        city: "Anytown",
        zip: "12345",
      },
      phoneNumbers: [
        "555-1234",
        "555-5678"
      ]
    }
    ''';

    // 将 JSON5 字符串解析为 Dart Map
    Map<String, dynamic> json5Map = await json5Decode(json5String);

    // 使用生成的 fromJson5 方法将 Map 转换为 User 对象
    return User.fromJson5(json5Map);
  }

  // 这是一个简单的 json5Decode 函数,使用 json5_model 插件的底层实现
  Future<Map<String, dynamic>> json5Decode(String json5String) async {
    // 注意:这里直接调用 json5_model 的底层实现可能不是一个好方法,
    // 因为 json5_model 通常是通过生成的代码来工作的。
    // 但为了演示目的,我们可以使用这种方式。
    // 在实际项目中,你应该使用生成的代码来进行序列化/反序列化。
    // 如果你需要直接解码 JSON5 字符串,你可能需要查看 json5 包的文档。
    // 但在这个例子中,我们假设 json5String 已经被正确解析为 Dart Map。
    // 正常情况下,你应该直接使用 User.fromJson5(json5DecodedMap)。
    // 下面的代码只是为了演示如何模拟这个过程。
    
    // 这里通常你会使用 json5 包的解析器,但为了简化,我们直接返回预解析的 Map。
    // 在实际使用中,你应该替换为真正的 JSON5 解析逻辑。
    // 例如:import 'package:json5/json5.dart'; 然后使用 Json5.decode(json5String);
    return {
      "name": "John Doe",
      "age": 30,
      "email": "john.doe@example.com",
      "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "zip": "12345",
      },
      "phoneNumbers": ["555-1234", "555-5678"],
    }; // 注意:这只是一个模拟的 Map,你应该使用真正的 JSON5 解析器。
  }
}

注意:上面的 json5Decode 函数是一个模拟示例,用于演示如何解析 JSON5 字符串。在实际项目中,你应该使用 json5 包的解析器来解析 JSON5 字符串,并将其结果传递给 User.fromJson5 方法。上面的代码只是为了演示整个流程,而 json5Decode 函数的具体实现应该基于 json5 包的文档进行。

由于 json5_model 插件通常通过生成的代码来处理序列化/反序列化,因此你通常不需要直接解析 JSON5 字符串。相反,你应该使用生成的 fromJson5toJson5 方法来处理数据。

回到顶部