Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openapi2conv: convert references in nested additionalProperties schemas #1047

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions openapi2conv/openapi2_conv.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,11 +513,7 @@ func ToV3SchemaRef(schema *openapi2.SchemaRef) *openapi3.SchemaRef {
MaxProps: schema.Value.MaxProps,
AllOf: make(openapi3.SchemaRefs, len(schema.Value.AllOf)),
Properties: make(openapi3.Schemas),
AdditionalProperties: schema.Value.AdditionalProperties,
}

if schema.Value.AdditionalProperties.Schema != nil {
v3Schema.AdditionalProperties.Schema.Ref = ToV3Ref(schema.Value.AdditionalProperties.Schema.Ref)
AdditionalProperties: toV3AdditionalProperties(schema.Value.AdditionalProperties),
}

if schema.Value.Discriminator != "" {
Expand Down Expand Up @@ -551,6 +547,27 @@ func ToV3SchemaRef(schema *openapi2.SchemaRef) *openapi3.SchemaRef {
}
}

func toV3AdditionalProperties(from openapi3.AdditionalProperties) openapi3.AdditionalProperties {
return openapi3.AdditionalProperties{
Has: from.Has,
Schema: convertRefsInV3SchemaRef(from.Schema),
}
}

func convertRefsInV3SchemaRef(from *openapi3.SchemaRef) *openapi3.SchemaRef {
if from == nil {
return nil
}
to := *from
to.Ref = ToV3Ref(to.Ref)
if to.Value != nil {
v := *from.Value
to.Value = &v
to.Value.AdditionalProperties = toV3AdditionalProperties(to.Value.AdditionalProperties)
}
return &to
}

var ref2To3 = map[string]string{
"#/definitions/": "#/components/schemas/",
"#/responses/": "#/components/responses/",
Expand Down
128 changes: 128 additions & 0 deletions openapi2conv/openapi2_conv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,134 @@ func TestConvOpenAPIV2ToV3(t *testing.T) {
require.JSONEq(t, exampleV3, string(data))
}

func TestConvOpenAPIV2ToV3WithAdditionalPropertiesSchemaRef(t *testing.T) {
v2 := []byte(`
{
"basePath": "/v2",
"host": "test.example.com",
"info": {
"title": "MyAPI",
"version": "0.1"
},
"paths": {
"/foo": {
"get": {
"operationId": "getFoo",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "returns all information",
"schema":{
"type":"object",
"additionalProperties":{
"$ref":"#/definitions/Foo"
}
}
}
},
"summary": "get foo"
}
}
},
"definitions": {
"Foo": {
"type": "object",
"properties": {
"a": {
"type": "string"
}
}
}
},
"schemes": [
"http"
],
"swagger": "2.0"
}
`)

var doc2 openapi2.T
err := json.Unmarshal(v2, &doc2)
require.NoError(t, err)

doc3, err := ToV3(&doc2)
require.NoError(t, err)
err = doc3.Validate(context.Background())
require.NoError(t, err)

responseSchema := doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value
require.Equal(t, &openapi3.Types{"object"}, responseSchema.Type)
require.Equal(t, "#/components/schemas/Foo", responseSchema.AdditionalProperties.Schema.Ref)
}

func TestConvOpenAPIV2ToV3WithNestedAdditionalPropertiesSchemaRef(t *testing.T) {
v2 := []byte(`
{
"basePath": "/v2",
"host": "test.example.com",
"info": {
"title": "MyAPI",
"version": "0.1"
},
"paths": {
"/foo": {
"get": {
"operationId": "getFoo",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "returns all information",
"schema":{
"type":"object",
"additionalProperties":{
"type":"object",
"additionalProperties":{
"$ref":"#/definitions/Foo"
}
}
}
}
},
"summary": "get foo"
}
}
},
"definitions": {
"Foo": {
"type": "object",
"properties": {
"a": {
"type": "string"
}
}
}
},
"schemes": [
"http"
],
"swagger": "2.0"
}
`)

var doc2 openapi2.T
err := json.Unmarshal(v2, &doc2)
require.NoError(t, err)

doc3, err := ToV3(&doc2)
require.NoError(t, err)
err = doc3.Validate(context.Background())
require.NoError(t, err)

responseSchema := doc3.Paths.Value("/foo").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value
require.Equal(t, &openapi3.Types{"object"}, responseSchema.Type)
require.Equal(t, &openapi3.Types{"object"}, responseSchema.AdditionalProperties.Schema.Value.Type)
require.Equal(t, "#/components/schemas/Foo", responseSchema.AdditionalProperties.Schema.Value.AdditionalProperties.Schema.Ref)
}

const exampleV2 = `
{
"basePath": "/v2",
Expand Down
Loading