From 76fdbccfe1fce3496e9fdf1b755bec4841928133 Mon Sep 17 00:00:00 2001 From: Dani Maarouf Date: Thu, 2 Oct 2025 23:58:41 -0400 Subject: [PATCH] openapi2conv: fix allOf inside additionalProperties Signed-off-by: Dani Maarouf --- openapi2conv/openapi2_conv.go | 8 +++ openapi2conv/openapi2_conv_test.go | 81 ++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go index 37c70eca..e50e1518 100644 --- a/openapi2conv/openapi2_conv.go +++ b/openapi2conv/openapi2_conv.go @@ -568,6 +568,14 @@ func convertRefsInV3SchemaRef(from *openapi3.SchemaRef) *openapi3.SchemaRef { to.Value.Items.Ref = ToV3Ref(to.Value.Items.Ref) } to.Value.AdditionalProperties = toV3AdditionalProperties(to.Value.AdditionalProperties) + + if len(to.Value.AllOf) > 0 { + allOf := make(openapi3.SchemaRefs, len(to.Value.AllOf)) + for i, schemaRef := range to.Value.AllOf { + allOf[i] = convertRefsInV3SchemaRef(schemaRef) + } + to.Value.AllOf = allOf + } } return &to } diff --git a/openapi2conv/openapi2_conv_test.go b/openapi2conv/openapi2_conv_test.go index 659ccb69..ce342378 100644 --- a/openapi2conv/openapi2_conv_test.go +++ b/openapi2conv/openapi2_conv_test.go @@ -193,6 +193,87 @@ func TestConvOpenAPIV2ToV3WithNestedAdditionalPropertiesSchemaRef(t *testing.T) require.Equal(t, "#/components/schemas/Foo", responseSchema.AdditionalProperties.Schema.Value.AdditionalProperties.Schema.Ref) } +func TestConvOpenAPIV2ToV3WithAllOfInsideAdditionalProperties(t *testing.T) { + v2 := []byte(` +{ + "basePath": "/v2", + "host": "test.example.com", + "info": { + "title": "MyAPI", + "version": "0.1" + }, + "paths": { + "/v1/objStatus": { + "get": { + "produces": [ + "application/json" + ], + "responses": { + "200": { + "schema": { + "type": "object", + "properties": { + "result": { + "type": "object", + "additionalProperties": { + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/ObjectInfo" + } + ], + "additionalProperties": { + "allOf": [ + { + "$ref": "#/definitions/ObjectInfo" + } + ] + } + } + } + } + }, + "description": "Success" + } + } + } + } + }, + "definitions": { + "ObjectInfo": { + "type": "object", + "properties": { + "object_id": { + "type": "string", + "format": "uuid" + } + } + } + }, + "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("/v1/objStatus").Get.Responses.Value("200").Value.Content.Get("application/json").Schema.Value + require.Equal(t, &openapi3.Types{"object"}, responseSchema.Type) + resultSchema := responseSchema.Properties["result"].Value + require.Equal(t, &openapi3.Types{"object"}, resultSchema.Type) + require.Equal(t, "#/components/schemas/ObjectInfo", resultSchema.AdditionalProperties.Schema.Value.AllOf[0].Ref) + require.Equal(t, "#/components/schemas/ObjectInfo", resultSchema.AdditionalProperties.Schema.Value.AdditionalProperties.Schema.Value.AllOf[0].Ref) +} + const exampleV2 = ` { "basePath": "/v2",