Flutterでopenapi-generator-cliを使っているとき、null-aware-elementsで失敗する際の対応
こんにちは、Rerurate_514と申します。
今回はこのエラーを修正した時の対応を書いたものです。
以下エラー。
task: [gen-api-from-openapi-dir] flutter pub run build_runner build --delete-conflicting-outputs
Deprecated. Use `dart run` instead.
0s json_serializable on 18 inputs: 9 skipped; lib/src/model/error.dart
0s copy_with_extension_gen on 18 inputs
0s source_gen:combining_builder on 18 inputs
Building, incremental build.
log output for json_serializable on lib/src/model/error.dart
W The language version (3.5.0) of this package (openapi) does not match the required range `^3.8.0`.
Edit pubspec.yaml to include an SDK constraint of at least ^3.8.0.
environment:
sdk: ^3.8.0
E An error `FormatterException` occurred while formatting the generated source for
`package:openapi/src/model/error.dart`
which was output to
`lib/src/model/error.json_serializable.g.part`.
This may indicate an issue in the generator, the input source code, or in the
source formatter.
Could not format because the source could not be parsed:
line 22, column 18 of .: This requires the 'null-aware-elements' language feature to be enabled.
╷
22 │ 'error': ?instance.error,
│ ^
╵
log output for build_runner
W SDK language version 3.11.0 is newer than `analyzer` language version 3.9.0. Run `flutter packages upgrade`.
Log overflowed the console, switching to line-by-line logging.
1s json_serializable on 18 inputs: 17 skipped, 1 same
0s copy_with_extension_gen on 18 inputs; lib/openapi.dart
0s copy_with_extension_gen on 18 inputs: 18 skipped
0s source_gen:combining_builder on 18 inputs; lib/openapi.dart
0s source_gen:combining_builder on 18 inputs: 18 skipped
Running the post build.
Writing the asset graph.
Failed to build with build_runner in 2s with warnings; wrote 1 output.
Failed to update packages.
task: Failed to run task "gen-api": task: Failed to run task "gen-api-from-openapi-dir": exit status 1経緯
まず私はopenapiの生成をhonoのopenapi-zodを使用して行っておりました。
そして以下のようなコードを書いてopenapi.jsonを生成しました。
import { z } from "@hono/zod-openapi";
export const ErrorSchema = z.object({
code: z.number().openapi({ example: 400 }),
message: z.string().openapi({ example: "データの取得に失敗しました。" }),
error: z.string().optional().openapi({ example: 'Bad Request' }),
}).openapi('Error');ここで注目してほしいのはerrorのoptionalです。これはなくてもいいプロパティにつけるものですが、これが問題の引き金になりました。
ここで生成されたopenapi.jsonをFlutter側で使用してクラスを生成していきます。
そして、生成されたopenapiディレクトリの中でflutter pub run build_runner buildをしたところ、上記のようなエラーになりました。
これはnull-aware-elements構文がdartのsdkの3.8以上で実装されているのに、openapiで生成されるppubspec.yamlのsdkバージョンが
environment:
sdk: '>=3.5.0 <4.0.0'となっていて、3.5が下限になっているため、新しい構文が使用不可となってしまうことに起因します。
nullawareについては以下の記事でも見てください。


解決
まず、このコマンドを打ちます。
openapi-generator-cli author template -g dart-dio -o ./templatesこれはopenapiの生成ファイルのテンプレートを集めたものです。
ここのpubspec.mustache以外は消します。

するとこうなると思います。
中身を見てみると、
name: {{pubName}}
version: {{pubVersion}}
description: {{pubDescription}}
homepage: {{pubHomepage}}
{{#pubRepository}}
repository: {{.}}
{{/pubRepository}}
{{#pubPublishTo}}
publish_to: {{.}}
{{/pubPublishTo}}
environment:
sdk: '>={{^useJsonSerializable}}2.18.0{{/useJsonSerializable}}{{#useJsonSerializable}}3.5.0{{/useJsonSerializable}} <4.0.0'
dependencies:
dio: '^5.7.0'
{{#useBuiltValue}}
one_of: '>=1.5.0 <2.0.0'
one_of_serializer: '>=1.5.0 <2.0.0'
built_value: '>=8.4.0 <9.0.0'
built_collection: '>=5.1.1 <6.0.0'
{{/useBuiltValue}}
{{#useEquatable}}
equatable: '^2.0.7'
{{/useEquatable}}
{{#useJsonSerializable}}
{{^skipCopyWith}}
copy_with_extension: '^7.1.0'
{{/skipCopyWith}}
json_annotation: '^4.9.0'
{{/useJsonSerializable}}
{{#useDateLibTimeMachine}}
time_machine: ^0.9.17
{{/useDateLibTimeMachine}}
dev_dependencies:
{{#useBuiltValue}}
built_value_generator: '>=8.4.0 <9.0.0'
build_runner: any
{{/useBuiltValue}}
{{#useJsonSerializable}}
build_runner: any
{{^skipCopyWith}}
copy_with_extension_gen: ^7.1.0
{{/skipCopyWith}}
json_serializable: '^6.9.3'
{{/useJsonSerializable}}
test: '^1.16.0'
となっているので、
environment:
sdk: '>={{^useJsonSerializable}}2.18.0{{/useJsonSerializable}}{{#useJsonSerializable}}3.5.0{{/useJsonSerializable}} <4.0.0'
の部分を
environment:
sdk: '>={{^useJsonSerializable}}2.18.0{{/useJsonSerializable}}{{#useJsonSerializable}}3.11.0{{/useJsonSerializable}} <4.0.0'
とでも書き換えておきます。
そして保存。
openapiの生成コマンドの引数に改変したテンプレートを使用するように追記します。
-t ./templates
自分が使っているのはこれ
openapi-generator-cli generate -i api-schema/openapi.json -g dart-dio -o openapi -c openapi-config.yaml -t ./templates一旦生成されたディレクトリを消してから再生成すると、build_runnerのエラーが消えるかと思います。
余談
自分はtask.yamlでコマンドを管理していて、task gen-apiの一つですべて実行するようにしています。
gen-api:
cmds:
- openapi-generator-cli validate -i api-schema/openapi.json
- openapi-generator-cli generate -i api-schema/openapi.json -g dart-dio -o openapi -c openapi-config.yaml -t ./templates
- task: gen-api-from-openapi-dir
gen-api-from-openapi-dir:
dir: ./openapi
cmds:
- flutter pub run build_runner build --delete-conflicting-outputsよかったら使ってみてください。
