如何在另一个代码生成器的顶部运行代码生成器?

时间:2019-12-27 17:18:54

标签: dart

使用source_gen堆栈来生成代码生成器,如何使生成器生成将作为另一生成器(更具体地说是json_serializable的输入)的代码?

例如,考虑:

class Example extends Generator {
  @override
  String generate(LibraryReader library, BuildStep buildStep) {
    return '''
@JsonSerializable(nullable: false)
class Person {
  final String firstName;
  final String lastName;
  final DateTime dateOfBirth;
  Person({this.firstName, this.lastName, this.dateOfBirth});
  factory Person.fromJson(Map<String, dynamic> json) => _PersonFromJson(json);
  Map<String, dynamic> toJson() => _PersonToJson(this);
}
''';
  }
}

这是代码生成器的示例,该代码生成器输出代码,然后需要将其发送到json_serializable

我该怎么做才能使json_serializable在此处正确生成?

3 个答案:

答案 0 :(得分:3)

请查看build.yaml配置文件文档以获取更多信息,但是我认为您应该使用applies_builders param,它允许在定义的构建之后执行另一构建。

该示例显示了一个生成器,该生成器生成.tar.gz文件,然后执行另一个将.tar.gz文件作为输入的构建

builders:
  # The regular builder config, creates .tar.gz files.
  regular_builder:
    import: "package:my_package/builder.dart"
    builder_factories: ["myBuilder"]
    build_extensions: {".dart": [".tar.gz"]}
    auto_apply: dependents
    apply_builders: [":archive_extract_builder"]
post_process_builders:
  # The post process builder config, extracts .tar.gz files.
  extract_archive_builder:
    import: "package:my_package/extract_archive_builder.dart"
    builder_factory: "myExtractArchiveBuilder"
    input_extensions: [".tar.gz"]

因此,source_gen应该为您的构建实现

applies_builders: ["source_gen|combining_builder", "json_serializable"]

并配置其他构建器

json_serializable:
    import: "package:json_serializable/builder.dart"
    builder_factories: ["jsonSerializable"]
    build_extensions: {".dart": ["json_serializable.g.part"]}
    auto_apply: dependents
    build_to: cache
    applies_builders: ["source_gen|combining_builder"]

答案 1 :(得分:2)

仅使用注释是不可能的,因为可能有两个包都带有@JsonSerializable注释

有两种情况:

  • 您知道在生成器之后还应该运行其他哪些生成器。


class Example extends Generator {
    @override
    String generate(LibraryReader library, BuildStep buildStep) {
      return JsonSerializable().generate('''
          @JsonSerializable(nullable: false)
          class Person {
            final String firstName;
            final String lastName;
            final DateTime dateOfBirth;
            Person({this.firstName, this.lastName, this.dateOfBirth});
            factory Person.fromJson(Map<String, dynamic> json) => _PersonFromJson(json);
            Map<String, dynamic> toJson() => _PersonToJson(this);
          }
        ''');
     }

}

  • 您不知道在生成器之后应该运行其他哪些生成器。

不幸的是,当前无法告诉source_gen您的生成器可能会生成需要代码生成的代码。

如果您要订阅,我在https://github.com/dart-lang/source_gen/issues/442处创建了一个问题

答案 2 :(得分:-2)

您可以通过调用jsonDecode()函数并将JSON字符串作为方法参数来解码JSON。

Map<String, dynamic> user = jsonDecode(jsonString);

print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');

现在,使用User.fromJson()构造函数从地图结构和toJson()方法构造新的User实例,该方法将User实例转换为地图。

employee.dart

class Employee {
  final String name;
  final String id;

  Employee(this.name, this.id);

  Employee.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        id = json['id'];

  Map<String, dynamic> toJson() =>
    {
      'name': name,
      'id': id,
    };
}

json_serializable是一个自动的源代码生成器,可以为您生成JSON序列化样板。

您需要一个常规依赖项和两个开发人员依赖项才能在项目中包含json_serializable

dependencies:
  json_annotation: ^0.2.3

dev_dependencies:
  build_runner: ^0.8.0
  json_serializable: ^0.5.0

有关JSON序列化的更多详细信息,您可以参考here

您还可以使用Smoke库。

它是Mirrors功能的子集,但同时具有基于Mirrors和基于Codegen的实现。它是由PolymerDart团队撰写的,因此与我们即将获得的“官方”产品非常接近。

在开发过程中,它将使用基于镜像的编码/解码;但是对于发布,您可以创建一个小型的转换器来生成代码。

Seth Ladd创建了a code sample here,我extended slightly支持子对象:

相关问题