openapi v3 petstore Pets not an array.
I tried the petstore example. Pets which is supposed to be an array of Pet, is being generated as an empty struct. Here is a dump of the Type
(*surface_v1.Type)(0xc00006e960)({
Name: (string) (len=4) "Pets",
Kind: (surface_v1.TypeKind) 0,
Description: (string) (len=41) "implements the service definition of Pets",
ContentType: (string) "",
Fields: ([]*surface_v1.Field) <nil>,
TypeName: (string) (len=4) "Pets"
}),
Digging into it, this is what I've come up with. I wanted to see if I was on the right track before submitting a PR.
diff --git a/plugins/gnostic-go-generator/render_types.go b/plugins/gnostic-go-generator/render_types.go
index e77707e..aacf56f 100644
--- a/plugins/gnostic-go-generator/render_types.go
+++ b/plugins/gnostic-go-generator/render_types.go
@@ -42,6 +42,8 @@ func (renderer *Renderer) RenderTypes() ([]byte, error) {
f.WriteLine(`}`)
} else if modelType.Kind == surface.TypeKind_OBJECT {
f.WriteLine(`type ` + modelType.TypeName + ` map[string]` + modelType.ContentType)
+ } else if modelType.Kind == 2 {
+ f.WriteLine(`type ` + modelType.TypeName + ` []` + modelType.ContentType)
} else {
f.WriteLine(`type ` + modelType.TypeName + ` interface {}`)
}
diff --git a/surface/model_openapiv3.go b/surface/model_openapiv3.go
index 70e0393..74146ea 100644
--- a/surface/model_openapiv3.go
+++ b/surface/model_openapiv3.go
@@ -104,6 +104,10 @@ func (b *OpenAPI3Builder) buildTypeFromSchemaOrReference(
t.ContentType = typeForRef(schema.AdditionalProperties.GetSchemaOrReference().GetReference().GetXRef())
}
}
+ if schema.Type == "array" && schema.Items != nil {
+ t.Kind = 2
+ _, t.ContentType, _ = b.typeForSchema(schema)
+ }
return t, err
} else {
return nil, errors.New("unable to determine service type for referenced schema " + name)
The only thing I could think of was creating a new TypeKind. I've tried adding it to the surface.proto but when I run protoc I get lots of changes besides just the new TypeKind.
This looks like a bug in encoding content/type. For example if we look at findPetsByStatus list response:
- v3: https://petstore3.swagger.io/#/pet/findPetsByStatus
"/pet/findByStatus": {
"get": {
"summary": "Finds Pets by status",
"description": "Multiple status values can be provided with comma separated strings",
"operationId": "findPetsByStatus",
"parameters": [],
"responses": {
"200": {
"description": "successful operation",
"content": {
"application/xml": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
}
},
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
}
}
- v2: https://petstore.swagger.io/#/pet/findPetsByStatus
"/pet/findByStatus": {
"get": {
"summary": "Finds Pets by status",
"description": "Multiple status values can be provided with comma separated strings",
"operationId": "findPetsByStatus",
"produces": [
"application/json",
"application/xml"
],
"parameters": [],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
}
}
}
}
I think these two methods should produce the same surface model. Current behaviour (encoding surface.Model as json) shows v2 ignores the produces field:
{
"name": "ListPetsResponses",
"description": "ListPetsResponses holds responses of ListPets",
"fields": [
{
"name": "200",
"type": "Pet",
"kind": "ARRAY"
}
]
}
whilst v3 tries to encode the application/json creating a layer of indirection:
{
"name": "listPetsOK",
"fields": [
{
"name": "application/json",
"type": "Pet",
"kind": "ARRAY"
}
]
},
{
"name": "ListPetsResponses",
"description": "ListPetsResponses holds responses of ListPets",
"fields": [
{
"name": "200",
"type": "listPetsOK",
"kind": "REFERENCE"
}
]
}
I think the fields need to be keyed on HTTP status and content/type. Would 200:application/json be okay?
Similar for parameters too, would be a nice to combine them to make the surface model generate the same code for both V2 and V3. v3:
types: {
name: "updatePetRequestBody"
fields: {
name: "application/json"
type: "Pet"
kind: REFERENCE
}
fields: {
name: "application/xml"
type: "Pet"
kind: REFERENCE
}
fields: {
name: "application/x-www-form-urlencoded"
type: "Pet"
kind: REFERENCE
}
}
types: {
name: "UpdatePetParameters"
description: "UpdatePetParameters holds parameters to UpdatePet"
fields: {
name: "request_body"
type: "updatePetRequestBody"
kind: REFERENCE
}
}
v2:
types: {
name: "UpdatePetParameters"
description: "UpdatePetParameters holds parameters to UpdatePet"
fields: {
name: "body"
type: "Pet"
kind: REFERENCE
}
}