oapi-codegenのx-go-type, x-go-type-name, x-go-nameの意味
(追記: 実行環境は https://zenn.dev/link/comments/ab9079c1882e1e)
oapi-codegen用に使える x-<name>
形式 の属性の説明があるがわかりにくかった。
- `x-go-type`: specifies Go type name. It allows you to specify the type name for a schema, and
will override any default value. This extended property isn't supported in all parts of
OpenAPI, so please refer to the spec as to where it's allowed. Swagger validation tools will
flag incorrect usage of this property.
- `x-go-name`: specifies Go field name. It allows you to specify the field name for a schema, and
will override any default value. This extended property isn't supported in all parts of
OpenAPI, so please refer to the spec as to where it's allowed. Swagger validation tools will
flag incorrect usage of this property.
- `x-go-type-name`: This property allows for assigning a Go type name to some part of a schema,
such as generating a type name for an anonymous object inside another object, or renaming
an enum. It differs from `x-go-type`, in that it doesn't completely replace some type reference,
but simply names it.
翻訳
oapi-codegenは次の拡張プロパティをサポートしています。
x-go-type: Go タイプ名を指定します。これにより、スキーマの型名を指定でき、デフォルト値がオーバーライドされます。この拡張プロパティは OpenAPI のすべての部分でサポートされているわけではないため、どこで許可されているかについては仕様を参照してください。Swagger 検証ツールは、このプロパティの不正な使用にフラグを立てます。
x-go-name: Go フィールド名を指定します。これにより、スキーマのフィールド名を指定でき、デフォルト値がオーバーライドされます。この拡張プロパティは OpenAPI のすべての部分でサポートされているわけではないため、どこで許可されているかについては仕様を参照してください。Swagger 検証ツールは、このプロパティの不正な使用にフラグを立てます。
x-go-type-name: このプロパティを使用すると、別のオブジェクト内の匿名オブジェクトの型名を生成したり、列挙型の名前を変更したりするなど、Go 型名をスキーマの一部に割り当てることができます。これはx-go-type、型参照を完全に置き換えるのではなく、単に名前を付けるだけであるという点で とは異なります。
x-go-json-ignore-: json 内のフィールドを完全に無視するには、タグを に設定します。
x-oapi-codegen-extra-tags: 生成された構造体フィールドに追加の Go フィールド タグを追加します。これは、タグベースの ORM または検証ライブラリとのインターフェースに役立ちます。追加される追加のタグは、生成される通常の json タグに追加されます。独自のjsonタグを指定すると、デフォルトのタグがオーバーライドされます。
型名の指定にx-go-type-nameを使うとconflictする
x,y 共通で使う型をoapitypeとして出力して、type aliasで参照するような形で使っていた。ここで型名を指定するのに x-go-type-name
を利用していた。
- x/main.yaml -> oapigen/x/server.go
- y/main.yaml -> oapigen/y/server.go
- x/main.yaml, y/main.yaml -> common.yaml -> oapigen/oapitype/types.go
📝 ここで、x,yから適切にoapitypeをimportするために生成される型の名前は明示的に固定したい。
ここで以下のようなcommon.yamlを生成して利用していた。
openapi: 3.0.3
info:
title: api
version: 0.0.0
paths:
/_error:
get:
operationId: error
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: OK
components:
schemas:
error:
description: error response body
type: object
properties:
code:
type: string
message:
type: string
x-go-type-name: Error # 生成される型の名前を Error にしたい
以下のようなエラーが出る。どうやらtype aliasと生成される型名が衝突するらしい。
$ oapi-codegen --config tools/oapi-conf/type.yaml bundle3/common_types.yaml
2023/06/07 15:57:00 ----------------------------------------
2023/06/07 15:57:00 GenerateTypes() mismatch (-prevType +typ):
codegen.TypeDefinition{
TypeName: "Error",
- JsonName: "error",
+ JsonName: "",
Schema: codegen.Schema{
- GoType: "Error",
+ GoType: (
+ """
+ struct {
+ Code *string`json:"code,omitempty"`
+ Message *string`json:"message,omitempty"`
+ }
+ """
+ ),
RefType: "",
ArrayType: nil,
EnumValues: nil,
- Properties: nil,
+ Properties: []codegen.Property{
+ {
+ JsonFieldName: "code",
+ Schema: codegen.Schema{GoType: "string", DefineViaAlias: true, OAPISchema: &openapi3.Schema{...}},
+ Extensions: map[string]any{},
+ },
+ {
+ JsonFieldName: "message",
+ Schema: codegen.Schema{GoType: "string", DefineViaAlias: true, OAPISchema: &openapi3.Schema{...}},
+ Extensions: map[string]any{},
+ },
+ },
HasAdditionalProperties: false,
- AdditionalPropertiesType: nil,
+ AdditionalPropertiesType: &codegen.Schema{GoType: "interface{}"},
- AdditionalTypes: []codegen.TypeDefinition{
- {
- TypeName: "Error",
- Schema: codegen.Schema{
- GoType: "struct {\n Code *string`json:\""...,
- Properties: []codegen.Property{...},
- AdditionalPropertiesType: &codegen.Schema{...},
- Description: "error response body",
- ...
- },
- },
- },
+ AdditionalTypes: nil,
SkipOptionalPointer: false,
Description: "error response body",
UnionElements: nil,
Discriminator: nil,
- DefineViaAlias: true,
+ DefineViaAlias: false,
- OAPISchema: nil,
+ OAPISchema: &openapi3.Schema{
+ Extensions: map[string]any{"x-go-type-name": string("Error")},
+ Type: "object",
+ Description: "error response body",
+ Properties: openapi3.Schemas{
+ "code": &{Value: &openapi3.Schema{...}},
+ "message": &{Value: &openapi3.Schema{...}},
+ },
+ },
},
}
2023/06/07 15:57:00 ----------------------------------------
error generating code: error generating type definitions: error generating code for type definitions: duplicate typename 'Error' detected, can't auto-rename, please use x-go-name to specify your own name for one of them
error generating code: error generating type definitions: error generating code for type definitions: duplicate typename 'Error' detected, can't auto-rename, please use x-go-name to specify your own name for one of them
これがエラーメッセージ。x-go-nameで指定してくれと言われているが、READMEを読んだときにはフィールド名の指定に利用されるように見えた。
環境
- go -- go version go1.19.9 darwin/amd64
- oapi-codegen -- v1.13.0
type.yaml
package: oapitype
generate:
models: true
compatibility:
always-prefix-enum-values: true
x-go-type, x-go-type-name, x-go-name の意味
x-go-nameで固定できるように変わったのか。(なんでfield用のものなのに型に効くんだ)
- x-go-type-nameの指定は生成される型名を固定するために使っていたような記憶(思い出す)
実験してみたところ以下のような形で動いていたようだった。
- x-go-name 生成されるstructの型名を変更 (フィールドに指定する場合にはフィールド名を変更)
- x-go-type-name その名前のaliasを設定
- x-go-type その型を利用する
つまりこういうこと。
openapi: 3.0.3
info:
title: api
version: 0.0.0
paths:
/_error:
get:
operationId: error
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: OK
components:
schemas:
error:
description: error response body
type: object
properties:
code:
type: string
x-go-type: myuuid.UUID
x-go-type-import:
name: myuuid # myuuid "github.com/google/uuid" とqualified import
path: github.com/google/uuid
message:
type: string
x-go-name: MessageString # field名の変更
x-oapi-codegen-extra-tags: # tagを追加
tag1: value1
json: message
yaml: message
x-go-name: XError # 生成される型を type XError struct { ... } に
x-go-type-name: YError # 別名(type alias)を作成 type YError = XError
生成結果はこの通り
// Package oapitype provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version (devel) DO NOT EDIT.
package oapitype
import (
myuuid "github.com/google/uuid"
)
// XError error response body
type XError = YError
// YError error response body
type YError struct {
Code *myuuid.UUID `json:"code,omitempty"`
MessageString *string `json:"message" tag1:"value1" yaml:"message"`
}
そんなに甘くない。 refと一緒に使うと期待しない結果になる
openapi: 3.0.3
info:
title: api
version: 0.0.0
paths:
/_error:
get:
operationId: error
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: OK
components:
schemas:
error:
description: error response body
type: object
properties:
createdAt:
$ref: "#/components/schemas/datetime"
updatedAt:
$ref: "#/components/schemas/datetime"
datetime:
type: string
format: date-time
x-go-name: MyDateTime
これが以下の結果を返してしまう
// Package oapitype provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version (devel) DO NOT EDIT.
package oapitype
import (
"time"
)
// MyDateTime defines model for datetime.
type MyDateTime = time.Time
// Error error response body
type Error struct {
MyDateTime *MyDateTime `json:"createdAt,omitempty"`
MyDateTime *MyDateTime `json:"updatedAt,omitempty"`
}
以下のようにyamlを変える。
openapi: 3.0.3
info:
title: api
version: 0.0.0
paths:
/_error:
get:
operationId: error
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: OK
components:
schemas:
error:
description: error response body
type: object
properties:
createdAt:
$ref: "#/components/schemas/datetime"
updatedAt:
$ref: "#/components/schemas/datetime"
x-go-type-name: MyError # 追加
datetime:
type: string
format: date-time
x-go-name: MyDateTime
x-go-type-name: DateTimeAlias # 追加
出力結果
// Package oapitype provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version v1.13.0 DO NOT EDIT.
package oapitype
import (
"time"
)
// MyDateTime defines model for datetime.
type MyDateTime = time.Time
// Error error response body
type Error = MyError
// MyError error response body
type MyError struct {
MyDateTime *MyDateTime `json:"createdAt,omitempty"`
MyDateTime *MyDateTime `json:"updatedAt,omitempty"`
}