Repository: getkin/kin-openapi
Pull request #875 (2023-11-27 10:34:52)

openapi3: rename type of Components.Responses to ResponseBodies (from Responses)


Patch:
diff --git a/.github/docs/openapi3.txt b/.github/docs/openapi3.txt
index 82a5e0b..571f7da 100644
--- a/.github/docs/openapi3.txt
+++ b/.github/docs/openapi3.txt
@@ -87,6 +87,7 @@ type RequestBody struct{ ... }
 type RequestBodyRef struct{ ... }
 type Response struct{ ... }
     func NewResponse() *Response
+type ResponseBodies map[string]*ResponseRef
 type ResponseRef struct{ ... }
 type Responses map[string]*ResponseRef
     func NewResponses() Responses
diff --git a/README.md b/README.md
index b2c1920..1e40514 100644
--- a/README.md
+++ b/README.md
@@ -275,7 +275,10 @@ func safeErrorMessage(err *openapi3.SchemaError) string {
 
 This will change the schema validation errors to return only the `Reason` field, which is guaranteed to not include the original value.
 
-## Sub-v0 breaking API changes
+## CHANGELOG: Sub-v0 breaking API changes
+
+### v0.121.0
+* Introduce `openapi3.RequestBodies` (an alias on `map[string]*openapi3.ResponseRef`) and use it in place of `openapi3.Responses` for field `openapi3.Components.Responses`.
 
 ### v0.116.0
 * Dropped `openapi3filter.DefaultOptions`. Use `&openapi3filter.Options{}` directly instead.
diff --git a/openapi3/components.go b/openapi3/components.go
index a645b77..5119e86 100644
--- a/openapi3/components.go
+++ b/openapi3/components.go
@@ -16,7 +16,7 @@ type Components struct {
 	Parameters      ParametersMap   `json:"parameters,omitempty" yaml:"parameters,omitempty"`
 	Headers         Headers         `json:"headers,omitempty" yaml:"headers,omitempty"`
 	RequestBodies   RequestBodies   `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
-	Responses       Responses       `json:"responses,omitempty" yaml:"responses,omitempty"`
+	Responses       ResponseBodies  `json:"responses,omitempty" yaml:"responses,omitempty"`
 	SecuritySchemes SecuritySchemes `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
 	Examples        Examples        `json:"examples,omitempty" yaml:"examples,omitempty"`
 	Links           Links           `json:"links,omitempty" yaml:"links,omitempty"`
@@ -142,10 +142,10 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp
 	}
 	sort.Strings(responses)
 	for _, k := range responses {
-		v := components.Responses[k]
 		if err = ValidateIdentifier(k); err != nil {
 			return fmt.Errorf("response %q: %w", k, err)
 		}
+		v := components.Responses[k]
 		if err = v.Validate(ctx); err != nil {
 			return fmt.Errorf("response %q: %w", k, err)
 		}
diff --git a/openapi3/internalize_refs.go b/openapi3/internalize_refs.go
index 30088ce..98c0e7e 100644
--- a/openapi3/internalize_refs.go
+++ b/openapi3/internalize_refs.go
@@ -158,7 +158,7 @@ func (doc *T) addResponseToSpec(r *ResponseRef, refNameResolver RefNameResolver,
 		doc.Components = &Components{}
 	}
 	if doc.Components.Responses == nil {
-		doc.Components.Responses = make(Responses)
+		doc.Components.Responses = make(ResponseBodies)
 	}
 	doc.Components.Responses[name] = &ResponseRef{Value: r.Value}
 	r.Ref = "#/components/responses/" + name
@@ -313,7 +313,7 @@ func (doc *T) derefLinks(ls Links, refNameResolver RefNameResolver, parentIsExte
 	}
 }
 
-func (doc *T) derefResponses(es Responses, refNameResolver RefNameResolver, parentIsExternal bool) {
+func (doc *T) derefResponses(es map[string]*ResponseRef, refNameResolver RefNameResolver, parentIsExternal bool) {
 	for _, e := range es {
 		isExternal := doc.addResponseToSpec(e, refNameResolver, parentIsExternal)
 		if e.Value != nil {
diff --git a/openapi3/response.go b/openapi3/response.go
index 61d859e..37f531a 100644
--- a/openapi3/response.go
+++ b/openapi3/response.go
@@ -11,12 +11,40 @@ import (
 	"github.com/go-openapi/jsonpointer"
 )
 
+type ResponseBodies map[string]*ResponseRef
+
+var _ jsonpointer.JSONPointable = (*ResponseRef)(nil)
+
+// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
+func (m ResponseBodies) JSONLookup(token string) (interface{}, error) {
+	if v, ok := m[token]; !ok || v == nil {
+		return nil, fmt.Errorf("no response body %q", token)
+	} else if ref := v.Ref; ref != "" {
+		return &Ref{Ref: ref}, nil
+	} else {
+		return v.Value, nil
+	}
+}
+
 // Responses is specified by OpenAPI/Swagger 3.0 standard.
 // See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#responses-object
 type Responses map[string]*ResponseRef
 
 var _ jsonpointer.JSONPointable = (*Responses)(nil)
 
+// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
+func (responses Responses) JSONLookup(token string) (interface{}, error) {
+	ref, ok := responses[token]
+	if !ok {
+		return nil, fmt.Errorf("invalid token reference: %q", token)
+	}
+
+	if ref != nil && ref.Ref != "" {
+		return &Ref{Ref: ref.Ref}, nil
+	}
+	return ref.Value, nil
+}
+
 func NewResponses() Responses {
 	r := make(Responses)
 	r["default"] = &ResponseRef{Value: NewResponse().WithDescription("")}
@@ -75,19 +103,6 @@ func (responses Responses) Validate(ctx context.Context, opts ...ValidationOptio
 	return nil
 }
 
-// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
-func (responses Responses) JSONLookup(token string) (interface{}, error) {
-	ref, ok := responses[token]
-	if !ok {
-		return nil, fmt.Errorf("invalid token reference: %q", token)
-	}
-
-	if ref != nil && ref.Ref != "" {
-		return &Ref{Ref: ref.Ref}, nil
-	}
-	return ref.Value, nil
-}
-
 // Response is specified by OpenAPI/Swagger 3.0 standard.
 // See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#response-object
 type Response struct {


Test patch:
diff --git a/openapi3/openapi3_test.go b/openapi3/openapi3_test.go
index 51073ab..9cfd277 100644
--- a/openapi3/openapi3_test.go
+++ b/openapi3/openapi3_test.go
@@ -302,45 +302,27 @@ func spec() *T {
 		},
 		Components: &Components{
 			Parameters: ParametersMap{
-				"someParameter": {
-					Value: parameter,
-				},
+				"someParameter": {Value: parameter},
 			},
 			RequestBodies: RequestBodies{
-				"someRequestBody": {
-					Value: requestBody,
-				},
+				"someRequestBody": {Value: requestBody},
 			},
-			Responses: Responses{
-				"someResponse": {
-					Value: response,
-				},
+			Responses: ResponseBodies{
+				"someResponse": {Value: response},
 			},
 			Schemas: Schemas{
-				"someSchema": {
-					Value: schema,
-				},
+				"someSchema": {Value: schema},
 			},
 			Headers: Headers{
-				"someHeader": {
-					Ref: "#/components/headers/otherHeader",
-				},
-				"otherHeader": {
-					Value: &Header{Parameter{Schema: &SchemaRef{Value: NewStringSchema()}}},
-				},
+				"someHeader":  {Ref: "#/components/headers/otherHeader"},
+				"otherHeader": {Value: &Header{Parameter{Schema: &SchemaRef{Value: NewStringSchema()}}}},
 			},
 			Examples: Examples{
-				"someExample": {
-					Ref: "#/components/examples/otherExample",
-				},
-				"otherExample": {
-					Value: NewExample(example),
-				},
+				"someExample":  {Ref: "#/components/examples/otherExample"},
+				"otherExample": {Value: NewExample(example)},
 			},
 			SecuritySchemes: SecuritySchemes{
-				"someSecurityScheme": {
-					Ref: "#/components/securitySchemes/otherSecurityScheme",
-				},
+				"someSecurityScheme": {Ref: "#/components/securitySchemes/otherSecurityScheme"},
 				"otherSecurityScheme": {
 					Value: &SecurityScheme{
 						Description: "Some security scheme",