前提
- openapi-generator
- generator-cli
- version:
7.11.0
- version:
- generatorName:
rust
- generator-cli
経緯
今まで対向APIのOpenAPI Specがなかったので自身のプロジェクトで書いていたが、対向APIを開発しているチームからOpenAPI Specが提供されるようになった。 そのため、提供されたOpenAPI Specを使ってopenapi-generatorでRustコードを生成した。
生成されたコードを使ってユニットテストを実行するとFAILするようになった。 エラーを読んでみると、対向APIのJSONレスポンスをDeserializeするときにエラーになっていた。
試してみた
提供されたOpenAPI Specは以下のような感じ。
paths: /example/user: get: response: 200: content: application/json: schema: allOf: $ref: '#/components/schemas/personal_info' ... components: schemas: personal_info: type: object properties: gender: type: integer format: int64 enum: - 1 - 2
生成されたEnumは以下のとおり。
#[serde(rename = "1")]
のようなattributeを使うと文字列のマッピングが行われるので、数値からDeserializeできずにエラーになってしまう。
期待するのは数値からEnumに変換できるコードだ。
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] pub enum Gender { #[serde(rename = "1")] Variant1, #[serde(rename = "2")] Variant2, }
openapi-generatorのrustのテンプレートをみてみると #isInteger
の場合に #[repr(i64)]
を付けてくれそう。
https://github.com/OpenAPITools/openapi-generator/blob/v7.11.0/modules/openapi-generator/src/main/resources/rust/model.mustache#L19-L22
でも、現状は以下の部分でEnumが生成されていそう。 https://github.com/OpenAPITools/openapi-generator/blob/v7.11.0/modules/openapi-generator/src/main/resources/rust/model.mustache#L178-L188
ということで、修正したのが以下のOpenAPI Spec。
paths: /example/user: get: response: 200: content: application/json: schema: allOf: $ref: '#/components/schemas/personal_info' ... components: schemas: personal_info: type: object properties: gender: $ref: '#/components/schemas/gender' # 変更点 ... gender: # genderをschemaに切り出した type: integer format: int32 enum: - 1 - 2
上記のOpenAPI Specからコードを再生成すると以下のような期待するコードになった。
#[repr(i64)] #[derive( Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr,)] pub enum Gender { Variant1 = 1, Variant2 = 2, }
format: int32
なのに #[repr(i64)]
なのが、少しモヤりポイント。
openapi-generator側のバグなのかわからないので、そこらへんはまだ調査中。