sudorandom / protoc-gen-connect-openapi

Plugin for generating OpenAPIv3 from protobufs matching the Connect RPC interface
MIT License
103 stars 7 forks source link

add flag to preserve ordering of proto fields in openapi spec schema #11

Closed gtshepard closed 6 months ago

gtshepard commented 6 months ago

Requesting flag to preserve ordering of proto fields in openapi spec schema

forcing lexicographical ordering of fields is undesirable in settings where controlling the order of properties is useful.

like readability of documentation page that renders the openapi spec. original gnostic project preserves this ordering.

Example

proto message fields are not in lexicographical order


message B {
  string x = 1;
  string z = 2;
  string y = 3;
}

message SomeRequest {
  string a = 1;
  string c = 2;
  B b = 3;
}

will result in an openapi schema where the fields are in lexicographical order

    some.pkg.v1.B:
      additionalProperties: false
      description: ""
      properties:
        x:
          additionalProperties: false
          description: ""
          title: x
          type: string
        y:
          additionalProperties: false
          description: ""
          title: y
          type: string
        z:
          additionalProperties: false
          description: ""
          title: z
          type: string
      title: B
      type: object
    some.pkg.v1.SomeRequest:
      additionalProperties: false
      description: ""
      properties:
        a:
          additionalProperties: false
          description: ""
          title: a
          type: string
        b:
          $ref: '#/components/schemas/some.pkg.v1.B'
          additionalProperties: false
          description: ""
          title: b
          type: object
        c:
          additionalProperties: false
          description: ""
          title: c
          type: string
      title: SomeRequest
      type: object

which is causing json documentation page to render like this

{
  "a": "string",
  "b": {
    "x": "string",
    "y": "string",
    "z": "string"
  },
  "c": "string"
}

expected it to follow ordering of proto fields like this

{
  "a": "string",
  "c": "string",
  "b": {
    "x": "string",
    "z": "string",
    "y": "string"
  },
}
sudorandom commented 6 months ago

This is a good idea, but this actually appears to be an issue with how jsonschema structures things. Maps don't guarantee order, especially in Go, but there's a further issue where I'm not sure if the order would be maintained in tools that ingest this openapi spec. It looks like there may be a convention to add a field that defines the order, usually with an X- prefix. So I can use the field number as a new property (maybe X-Field-Number) but it's unlikely that any tool using this openapi spec knows how to deal with that.

See here for more information: https://github.com/json-schema-org/json-schema-vocabularies/issues/7

gtshepard commented 6 months ago

thanks for getting back so quickly.

original gnostic project was able to preserve the ordering from my experience. from some digging found this old thread. might be of some use.

https://github.com/google/gnostic/issues/2#issuecomment-262604464

the tool im using to render the spec follows ordering defined in the spec as well.

sidenote great project. requires like no proto annotations to get this going and works seamlessly with server reflection. and love the base openapi spec idea. really simplifies things.

sudorandom commented 6 months ago

@gtshepard thanks for the praise!

I'm considering switching to https://pb33f.io/libopenapi/openapi/, which will give ordered maps for pretty much everything so it should be possible to maintain the order declared in the protobuf file. This will be a large undertaking though so I don't promise that it will be done soon :) I already made some good progress on it though, so let's see how it goes

sudorandom commented 6 months ago

@gtshepard I've made a new release that has a new openapi/json schema library which has the behavior that you want here. Cheers!

gtshepard commented 6 months ago

wow amazing! thank you