一个用于从支持多种环境的 json 文件创建配置文件类的生成器。

动机

如果您使用 json 文件来配置您的应用程序,您可能需要编写一个包含所有已定义变量及其数据类型的 dart 类。当您需要管理嵌套对象时,会更复杂。即使您想在 json 中添加或删除一个值,您也需要修改您的 dart 类。

如果您想管理环境,您需要手动为所需的每个环境编写文件路径。

json_config_generator 旨在帮助您简化配置文件和环境的管理过程。

安装

要使用 json_config_generator,您需要 build_runner/代码生成器的设置。
首先,通过将它们添加到您的 pubspec.yaml 文件中来安装 build_runnerjson_config_generator

pubspec.yaml

dependencies:
  json_config_annotation: ^0.1.0

dev_dependencies:
  build_runner:
  json_config_generator: ^0.1.0

如何使用

要使用此生成器,您需要创建一个以 $ 开头的空配置文件类,并使用 Configuration 注释定义您想要的环境。每个环境都有 namepath,如果有多个环境,生成器会创建一个 Enum 来表示环境。您还可以指定该 Enum 的名称。默认名称是 Environment。此外,您还需要添加一些导入。

config.dart

import 'package:json_config_annotation/json_config_annotation.dart';
import 'dart:convert';
import 'package:flutter/services.dart';

part 'config.g.dart'; //{dart file name}.g.dart

@Configuration(
  environmentEnumName: 'Env',
  environments:[
    Environment(name:'dev', path:'assets/config/dev.json'),
    Environment(name:'prd', path:'assets/config/prd.json'),
  ],
)
class $Config{}

假设有以下 json 文件

dev.json

{
  "base_url": "https://example.com",
  "custom_class": {
    "value_1": "dfgdfgdfgwqrrqwrqwrqweqwe324523b252dghfdhd",
    "value_2": "6Lez7aIaAAAAAN6qZG2343c252bv66b7yn5m8m6"
  },
  "int_value": 3,
  "double_value": 3.5,
  "boolean_value": true,
  "string_list": ["hello", "world"],
  "int_list": [1, 23, 5],
  "bool_list": [false, true, true],
  "custom_list": [
    {
      "value_1": "hello"
    },
    {
      "value_1": "world"
    }
  ]
}

生成器会创建

config.g.dart

enum Env { dev, prd }

class Config {
  Config._();

  static final instance = Config._();

  late String baseUrl;

  late _CustomClass customClass;

  late int intValue;

  late double doubleValue;

  late bool booleanValue;

  late List<String> stringList;

  late List<int> intList;

  late List<bool> boolList;

  late List<_CustomList> customList;

  Future<void> init(Env env) async {
    String path = '';
    switch (env) {
      case Env.dev:
        path = 'assets/config/dev.json';
        break;
      case Env.prd:
        path = 'assets/config/prd.json';
        break;
    }
    final jsonString = await rootBundle.loadString(path);
    final config = json.decode(jsonString) as Map<String, dynamic>;
    baseUrl = config['base_url'] as String;
    customClass =
        _CustomClass.fromJson(config['custom_class'] as Map<String, dynamic>);
    intValue = config['int_value'] as int;
    doubleValue = config['double_value'] as double;
    booleanValue = config['boolean_value'] as bool;
    stringList = (config['string_list'] as List).cast<String>();
    intList = (config['int_list'] as List).cast<int>();
    boolList = (config['bool_list'] as List).cast<bool>();
    customList = _CustomList.listFromJson(config['custom_list'] as List);
  }
}

class _CustomClass {
  const _CustomClass({required this.value1, required this.value2});

  factory _CustomClass.fromJson(Map<String, dynamic> customClass) =>
      _CustomClass(
        value1: customClass['value_1'] as String,
        value2: customClass['value_2'] as String,
      );

  final String value1;

  final String value2;
}

class _CustomList {
  const _CustomList({required this.value1});

  factory _CustomList.fromJson(Map<String, dynamic> customList) => _CustomList(
        value1: customList['value_1'] as String,
      );

  final String value1;

  static List<_CustomList> listFromJson(List data) =>
      data.map((e) => _CustomList.fromJson(e as Map<String, dynamic>)).toList();
}

要使用生成的配置,您需要调用 init 方法来初始化所有值。可以在 main 中调用它,并指定要使用的环境。

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Config.instance.init(Env.dev);
  runApp(const MyApp());
}

现在可以通过 instance 轻松访问字段

Config.instance.baseUrl;
Config.instance.customClass.value1;

支持的数据类型

- String
- int
- double
- bool
- CustomClass
- List<String>
- List<int>
- List<double>
- List<bool>
- List<CustomClass>

也可以创建嵌套类!

重要提示

  • 不支持可空值
  • 不支持动态值

运行生成器

要运行生成器,请使用以下命令之一

  • flutter pub run build_runner build
  • dart pub run build_runner build

注意事项

也可以创建一个只有一种 Environment 的配置。如果是这样,则不会创建 Enum,调用 init 方法时也不需要传递任何参数。

重要的是要知道生成器会取列表中的第一个值来确定列表的类型,所以要小心。

GitHub

查看 Github