Skip to content

Commit af43038

Browse files
wtertiusDmitriy LukiyanchukjamietannaJamie Tanna
authored
feat: add ability to tweak generated names (including use of initialisms)
As noted in #454, the generated code we produce defaults to performing `CamelCase` - which is fine - but doesn't take into account common initialisms that are idiomatic to Go. This was previously attempted in #1007, but we had to roll it back due to it changing underlying generated code, which would result in a breaking change for consumers. To avoid this, we can make this opt-in via a new output option, `name-normalizer`, which provides the ability to control the functionality. This is also available for folks using the project as a library, which makes it more convenient to change behaviour. Closes #454. Co-authored-by: Dmitriy Lukiyanchuk <dmitriy.lukiyanchuk@instamart.ru> Co-authored-by: Jamie Tanna <jamie@jamietanna.co.uk> Co-authored-by: Jamie Tanna <jamie.tanna@elastic.co>
1 parent fd4a0ef commit af43038

24 files changed

+3126
-16
lines changed

README.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3265,6 +3265,211 @@ func (a Thing) MarshalJSON() ([]byte, error) {
32653265

32663266
</details>
32673267

3268+
## Changing the names of generated types
3269+
3270+
As of `oapi-codegen` v2.2.0, it is now possible to use the `output-options` configuration's `name-normalizer` to define the logic for how to convert an OpenAPI name (i.e. an Operation ID or a Schema name) and construct a Go type name.
3271+
3272+
<details>
3273+
3274+
<summary>Example, using default configuration</summary>
3275+
3276+
By default, `oapi-codegen` will perform camel-case conversion, so for a spec such as:
3277+
3278+
```yaml
3279+
openapi: "3.0.0"
3280+
info:
3281+
version: 1.0.0
3282+
title: Example code for the `name-normalizer` output option
3283+
paths:
3284+
/api/pets/{petId}:
3285+
get:
3286+
summary: Get pet given identifier.
3287+
operationId: getHttpPet
3288+
parameters:
3289+
- name: petId
3290+
in: path
3291+
required: true
3292+
schema:
3293+
type: string
3294+
responses:
3295+
'200':
3296+
description: valid pet
3297+
content:
3298+
application/json:
3299+
schema:
3300+
$ref: '#/components/schemas/Pet'
3301+
components:
3302+
schemas:
3303+
Pet:
3304+
type: object
3305+
required:
3306+
- uuid
3307+
- name
3308+
properties:
3309+
uuid:
3310+
type: string
3311+
description: The pet uuid.
3312+
name:
3313+
type: string
3314+
description: The name of the pet.
3315+
Error:
3316+
required:
3317+
- code
3318+
- message
3319+
properties:
3320+
code:
3321+
type: integer
3322+
format: int32
3323+
description: Error code
3324+
message:
3325+
type: string
3326+
description: Error message
3327+
OneOf2things:
3328+
description: "Notice that the `things` is not capitalised"
3329+
oneOf:
3330+
- type: object
3331+
required:
3332+
- id
3333+
properties:
3334+
id:
3335+
type: integer
3336+
- type: object
3337+
required:
3338+
- id
3339+
properties:
3340+
id:
3341+
type: string
3342+
format: uuid
3343+
```
3344+
3345+
This will produce:
3346+
3347+
```go
3348+
// OneOf2things Notice that the `things` is not capitalised
3349+
type OneOf2things struct {
3350+
union json.RawMessage
3351+
}
3352+
3353+
// Pet defines model for Pet.
3354+
type Pet struct {
3355+
// Name The name of the pet.
3356+
Name string `json:"name"`
3357+
3358+
// Uuid The pet uuid.
3359+
Uuid string `json:"uuid"`
3360+
}
3361+
3362+
// The interface specification for the client above.
3363+
type ClientInterface interface {
3364+
// GetHttpPet request
3365+
GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error)
3366+
}
3367+
```
3368+
3369+
</details>
3370+
3371+
<details>
3372+
3373+
<summary>Example, using <code>ToCamelCaseWithInitialisms</code></summary>
3374+
3375+
By default, `oapi-codegen` will perform camel-case conversion, so for a spec such as:
3376+
3377+
```yaml
3378+
openapi: "3.0.0"
3379+
info:
3380+
version: 1.0.0
3381+
title: Example code for the `name-normalizer` output option
3382+
paths:
3383+
/api/pets/{petId}:
3384+
get:
3385+
summary: Get pet given identifier.
3386+
operationId: getHttpPet
3387+
parameters:
3388+
- name: petId
3389+
in: path
3390+
required: true
3391+
schema:
3392+
type: string
3393+
responses:
3394+
'200':
3395+
description: valid pet
3396+
content:
3397+
application/json:
3398+
schema:
3399+
$ref: '#/components/schemas/Pet'
3400+
components:
3401+
schemas:
3402+
Pet:
3403+
type: object
3404+
required:
3405+
- uuid
3406+
- name
3407+
properties:
3408+
uuid:
3409+
type: string
3410+
description: The pet uuid.
3411+
name:
3412+
type: string
3413+
description: The name of the pet.
3414+
Error:
3415+
required:
3416+
- code
3417+
- message
3418+
properties:
3419+
code:
3420+
type: integer
3421+
format: int32
3422+
description: Error code
3423+
message:
3424+
type: string
3425+
description: Error message
3426+
OneOf2things:
3427+
description: "Notice that the `things` is not capitalised"
3428+
oneOf:
3429+
- type: object
3430+
required:
3431+
- id
3432+
properties:
3433+
id:
3434+
type: integer
3435+
- type: object
3436+
required:
3437+
- id
3438+
properties:
3439+
id:
3440+
type: string
3441+
format: uuid
3442+
```
3443+
3444+
This will produce:
3445+
3446+
```go
3447+
// OneOf2things Notice that the `things` is not capitalised
3448+
type OneOf2things struct {
3449+
union json.RawMessage
3450+
}
3451+
3452+
// Pet defines model for Pet.
3453+
type Pet struct {
3454+
// Name The name of the pet.
3455+
Name string `json:"name"`
3456+
3457+
// UUID The pet uuid.
3458+
UUID string `json:"uuid"`
3459+
}
3460+
3461+
// The interface specification for the client above.
3462+
type ClientInterface interface {
3463+
// GetHTTPPet request
3464+
GetHTTPPet(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*http.Response, error)
3465+
}
3466+
```
3467+
3468+
</details>
3469+
3470+
3471+
For more details of what the resulting code looks like, check out [the test cases](internal/test/outputoptions/name-normalizer/).
3472+
32683473
## Examples
32693474

32703475
The [examples directory](examples) contains some additional cases which are useful examples for how to use `oapi-codegen`, including how you'd take the Petstore API and implement it with `oapi-codegen`.

configuration-schema.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,16 @@
182182
"array"
183183
]
184184
}
185+
},
186+
"name-normalizer": {
187+
"type": "string",
188+
"description": "NameNormalizer is the method used to normalize Go names and types, for instance converting the text `MyApi` to `MyAPI`. Corresponds with the constants defined for `codegen.NameNormalizerFunction`",
189+
"default": "ToCamelCase",
190+
"enum": [
191+
"ToCamelCase",
192+
"ToCamelCaseWithDigits",
193+
"ToCamelCaseWithInitialisms"
194+
]
185195
}
186196
}
187197
},
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
openapi: "3.0.0"
2+
info:
3+
version: 1.0.0
4+
title: Example code for the `name-normalizer` output option
5+
paths:
6+
/api/pets/{petId}:
7+
get:
8+
summary: Get pet given identifier.
9+
operationId: getHttpPet
10+
parameters:
11+
- name: petId
12+
in: path
13+
required: true
14+
schema:
15+
type: string
16+
responses:
17+
'200':
18+
description: valid pet
19+
content:
20+
application/json:
21+
schema:
22+
$ref: '#/components/schemas/Pet'
23+
components:
24+
schemas:
25+
Pet:
26+
type: object
27+
required:
28+
- uuid
29+
- name
30+
properties:
31+
uuid:
32+
type: string
33+
description: The pet uuid.
34+
name:
35+
type: string
36+
description: The name of the pet.
37+
Error:
38+
required:
39+
- code
40+
- message
41+
properties:
42+
code:
43+
type: integer
44+
format: int32
45+
description: Error code
46+
message:
47+
type: string
48+
description: Error message
49+
OneOf2things:
50+
description: "Notice that the `things` is not capitalised"
51+
oneOf:
52+
- type: object
53+
required:
54+
- id
55+
properties:
56+
id:
57+
type: integer
58+
- type: object
59+
required:
60+
- id
61+
properties:
62+
id:
63+
type: string
64+
format: uuid
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# yaml-language-server: $schema=../../../../../configuration-schema.json
2+
package: tocamelcasewithdigits
3+
generate:
4+
gorilla-server: true
5+
client: true
6+
models: true
7+
embedded-spec: true
8+
output: name_normalizer.gen.go
9+
output-options:
10+
skip-prune: true
11+
name-normalizer: ToCamelCaseWithDigits
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package tocamelcasewithdigits
2+
3+
//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml

0 commit comments

Comments
 (0)