Skip to content

Commit

Permalink
feat: add ability to tweak generated names (including use of initiali…
Browse files Browse the repository at this point in the history
…sms)

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>
  • Loading branch information
4 people committed May 4, 2024
1 parent fd4a0ef commit af43038
Show file tree
Hide file tree
Showing 24 changed files with 3,126 additions and 16 deletions.
205 changes: 205 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3265,6 +3265,211 @@ func (a Thing) MarshalJSON() ([]byte, error) {

</details>

## Changing the names of generated types

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.

<details>

<summary>Example, using default configuration</summary>

By default, `oapi-codegen` will perform camel-case conversion, so for a spec such as:

```yaml
openapi: "3.0.0"
info:
version: 1.0.0
title: Example code for the `name-normalizer` output option
paths:
/api/pets/{petId}:
get:
summary: Get pet given identifier.
operationId: getHttpPet
parameters:
- name: petId
in: path
required: true
schema:
type: string
responses:
'200':
description: valid pet
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
Pet:
type: object
required:
- uuid
- name
properties:
uuid:
type: string
description: The pet uuid.
name:
type: string
description: The name of the pet.
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
description: Error code
message:
type: string
description: Error message
OneOf2things:
description: "Notice that the `things` is not capitalised"
oneOf:
- type: object
required:
- id
properties:
id:
type: integer
- type: object
required:
- id
properties:
id:
type: string
format: uuid
```

This will produce:

```go
// OneOf2things Notice that the `things` is not capitalised
type OneOf2things struct {
union json.RawMessage
}

// Pet defines model for Pet.
type Pet struct {
// Name The name of the pet.
Name string `json:"name"`

// Uuid The pet uuid.
Uuid string `json:"uuid"`
}

// The interface specification for the client above.
type ClientInterface interface {
// GetHttpPet request
GetHttpPet(ctx context.Context, petId string, reqEditors ...RequestEditorFn) (*http.Response, error)
}
```

</details>

<details>

<summary>Example, using <code>ToCamelCaseWithInitialisms</code></summary>

By default, `oapi-codegen` will perform camel-case conversion, so for a spec such as:

```yaml
openapi: "3.0.0"
info:
version: 1.0.0
title: Example code for the `name-normalizer` output option
paths:
/api/pets/{petId}:
get:
summary: Get pet given identifier.
operationId: getHttpPet
parameters:
- name: petId
in: path
required: true
schema:
type: string
responses:
'200':
description: valid pet
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
Pet:
type: object
required:
- uuid
- name
properties:
uuid:
type: string
description: The pet uuid.
name:
type: string
description: The name of the pet.
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
description: Error code
message:
type: string
description: Error message
OneOf2things:
description: "Notice that the `things` is not capitalised"
oneOf:
- type: object
required:
- id
properties:
id:
type: integer
- type: object
required:
- id
properties:
id:
type: string
format: uuid
```

This will produce:

```go
// OneOf2things Notice that the `things` is not capitalised
type OneOf2things struct {
union json.RawMessage
}

// Pet defines model for Pet.
type Pet struct {
// Name The name of the pet.
Name string `json:"name"`

// UUID The pet uuid.
UUID string `json:"uuid"`
}

// The interface specification for the client above.
type ClientInterface interface {
// GetHTTPPet request
GetHTTPPet(ctx context.Context, petID string, reqEditors ...RequestEditorFn) (*http.Response, error)
}
```

</details>


For more details of what the resulting code looks like, check out [the test cases](internal/test/outputoptions/name-normalizer/).

## Examples

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`.
Expand Down
10 changes: 10 additions & 0 deletions configuration-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,16 @@
"array"
]
}
},
"name-normalizer": {
"type": "string",
"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`",
"default": "ToCamelCase",
"enum": [
"ToCamelCase",
"ToCamelCaseWithDigits",
"ToCamelCaseWithInitialisms"
]
}
}
},
Expand Down
64 changes: 64 additions & 0 deletions internal/test/outputoptions/name-normalizer/spec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Example code for the `name-normalizer` output option
paths:
/api/pets/{petId}:
get:
summary: Get pet given identifier.
operationId: getHttpPet
parameters:
- name: petId
in: path
required: true
schema:
type: string
responses:
'200':
description: valid pet
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
Pet:
type: object
required:
- uuid
- name
properties:
uuid:
type: string
description: The pet uuid.
name:
type: string
description: The name of the pet.
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
description: Error code
message:
type: string
description: Error message
OneOf2things:
description: "Notice that the `things` is not capitalised"
oneOf:
- type: object
required:
- id
properties:
id:
type: integer
- type: object
required:
- id
properties:
id:
type: string
format: uuid
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# yaml-language-server: $schema=../../../../../configuration-schema.json
package: tocamelcasewithdigits
generate:
gorilla-server: true
client: true
models: true
embedded-spec: true
output: name_normalizer.gen.go
output-options:
skip-prune: true
name-normalizer: ToCamelCaseWithDigits
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package tocamelcasewithdigits

//go:generate go run github.com/deepmap/oapi-codegen/v2/cmd/oapi-codegen --config=config.yaml ../spec.yaml

0 comments on commit af43038

Please sign in to comment.