Skip to content
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