discord-gophers / goapi-gen

This package contains a set of utilities for generating Go boilerplate code for services based on OpenAPI 3.0 API definitions
Apache License 2.0
117 stars 12 forks source link

Not possible to generate a struct with attributes in the same order as the API specs #105

Open yeforriak opened 2 months ago

yeforriak commented 2 months ago

I want to generate a struct with attributes ordered as defined in the OpenAPI specification doc.

Api specification:

    Settings:
      type: object
      required:
        - name
        - enabled
      properties:
        name:
          type: string
          enum: [ setting-a, setting-b, setting-c, setting-d ]
        enabled:
          type: boolean

The generated struct attributes are sorted alphabetically:

type Setting struct {
    Enabled bool        `json:"enabled"`
    Name    SettingName `json:"name"`
}

but I would like the struct to be defined as

type Setting struct {
        Name    SettingName `json:"name"`
    Enabled bool        `json:"enabled"`
}
Karitham commented 2 months ago

Hi, can I ask why you would need that? I understand your feature request perfectly but it reads to me like a XY problem. Is it just about the order of the actual fields?

Because at the end of the day the JSON will still have roughly random order fields, and if it's about malign we can run that on the generated code.

When you use the struct, you can also use any order so I'm failing to see the value behind such a feature request.

yeforriak commented 2 months ago

Hi, thanks for your prompt response.

The intention was to use the generated model directly to generate an HTTP response (json API) from the server code and I wanted to have some control over the order of the fields.

In my particular case, it is not a big deal since I can take care of the ordering in the UI code or even map it to another struct on the server side if needed.

When I was investigating this I found it interesting that there could be optimisations done by sorting struct attributes, see this

But anyway, I'm happy to close this issue. Thanks 👍

Karitham commented 2 months ago

When I was investigating this I found it interesting that there could be optimisations done by sorting struct attributes, see this

Go actually has a vet for this, https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/fieldalignment@v0.20.0 which we could likely integrate as a pass after generation of the fields.

I forgot exactly if there is a provided auto-fix for it, but adding this code to the ouput pipeline is not something I'm against. We explicitly do not guarantee order anywhere, we just sort the fields as part of pre-passes to make the output deterministic.

Unfortunately the openAPI spec represents them as a map so we'd need to switch to ordered maps. I think the openapi library we use did the change on their end but it'd be quite a big refactoring on our end. I do not mind either (or even both options).

Open to contributions, in the best case scenario it's a small 10 line changes somewhere here https://github.com/discord-gophers/goapi-gen/blob/main/codegen/codegen.go#L227-L235