How to run a code-generator on the top of another code-generator?

后端 未结 3 1171
遥遥无期
遥遥无期 2021-02-13 04:26

Using the source_gen stack to make a code generator, how can I make a generator that generates code that would be the input of another generator (more specifically json_se

相关标签:
3条回答
  • 2021-02-13 04:47

    It's not possible just with annotation because there maybe two packages that both have the @JsonSerializable annotation

    There are two situtations :

    • You know what other generators should run after your generator.

      • https://stackoverflow.com/a/59605830/6877472 is one of the solutions
      • you can use the other generator's code in your own generator and call their generator's.generate function. example code:
    
    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);
              }
            ''');
         }
    
    }
    
    
    • You don't know what other generators should run after your generator.

    Unfortunately currently there is no way to tell the source_gen that your generator may produce a code that needs code generation.

    I created an issue here https://github.com/dart-lang/source_gen/issues/442 if you want to subscribe

    0 讨论(0)
  • 2021-02-13 04:48

    Check the build.yaml config file documentation for more info, but I think you should use the applies_builders param that allows to execute another build after the defined one.

    The example shows a builder that generates .tar.gz files and then executes another build that takes the .tar.gz files as input

    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"]
    

    so with source_gen you should implement for your build

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

    and configure the other builder

    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"]
    
    0 讨论(0)
  • 2021-02-13 04:59

    You can decode the JSON by calling the jsonDecode() function, with the JSON string as the method argument.

    Map<String, dynamic> user = jsonDecode(jsonString);
    
    print('Howdy, ${user['name']}!');
    print('We sent the verification link to ${user['email']}.');
    

    Now, Use the User.fromJson() constructor, for constructing a new User instance from a map structure and a toJson() method, which converts a User instance into a map.

    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 is an automated source code generator that generates the JSON serialization boilerplate for you.

    You need one regular dependency, and two dev dependencies to include json_serializable in your project.

    dependencies:
      json_annotation: ^0.2.3
    
    dev_dependencies:
      build_runner: ^0.8.0
      json_serializable: ^0.5.0
    

    For more details on JSON serialization you can refer here

    you can also use the Smoke library.

    It's a subset of the Mirrors functionality but has both a Mirrors-based and a Codegen-based implementation. It's written by the PolymerDart team, so it's as close to "Official" as we're going to get.

    While developing, it'll use the Mirrors-based encoding/decoding; but for publishing you can create a small transformer that will generate code.

    Seth Ladd created a code sample here, which I extended slightly to support child-objects:

    0 讨论(0)
提交回复
热议问题