Repository: swaggest/openapi-go
Pull request #118 (2024-06-25 08:35:44)

Preserve existing media type value during response parsing

github-actions[bot]: ### Lines Of Code

| Language  | Files |    Lines    |    Code     | Comments |  Blanks   | Complexity |     Bytes      |
|-----------|-------|-------------|-------------|----------|-----------|------------|----------------|
| Go        | 21    | 3958 (-6)   | 2945 (-8)   | 214      | 799 (+2)  | 807        | 91K (-140B)    |
| Go (test) | 22    | 6381 (+178) | 4875 (+160) | 660      | 846 (+18) | 61 (+2)    | 164.3K (+4.2K) |
<!-- Sticky Pull Request CommentLOC -->
github-actions[bot]: ### Go API Changes

<pre>
# summary
Inferred base version: v0.2.51
Suggested version: v0.2.52
</pre>
<!-- Sticky Pull Request Commentgorelease -->
github-actions[bot]: ### Unit Test Coverage
total:									(statements)				46.0%
changed lines: (statements) 100.0%
<details><summary>Coverage of changed lines</summary>

|           File           |     Function      | Coverage |
|--------------------------|-------------------|----------|
| Total                    |                   | 100.0%   |
| openapi3/reflect.go      |                   | 100.0%   |
| openapi3/reflect.go:691  | parseJSONResponse | 100.0%   |
| openapi31/reflect.go     |                   | 100.0%   |
| openapi31/reflect.go:642 | parseJSONResponse | 100.0%   |

</details>

<details><summary>Coverage diff with base branch</summary>

|          File          |     Function      | Base Coverage | Current Coverage |
|------------------------|-------------------|---------------|------------------|
| Total                  |                   | 45.6%         | 46.0% (+0.4%)    |
| openapi3/entities.go   | WithContentItem   | 0.0%          | 100.0% (+100.0%) |
| openapi3/entities.go   | WithValue         | 0.0%          | 100.0% (+100.0%) |
| openapi3/jsonschema.go | fromSchemaArray   | 25.0%         | 100.0% (+75.0%)  |
| openapi3/reflect.go    | parseJSONResponse | 93.8%         | 94.4% (+0.6%)    |
| openapi31/entities.go  | WithContentItem   | 0.0%          | 100.0% (+100.0%) |
| openapi31/entities.go  | WithValue         | 0.0%          | 100.0% (+100.0%) |
| openapi31/reflect.go   | parseJSONResponse | 86.7%         | 88.2% (+1.5%)    |

</details>
<!-- Sticky Pull Request Commentunit-test -->

Patch:
diff --git a/openapi3/reflect.go b/openapi3/reflect.go
index afae59e..faf6742 100644
--- a/openapi3/reflect.go
+++ b/openapi3/reflect.go
@@ -717,13 +717,10 @@ func (r *Reflector) parseJSONResponse(resp *Response, oc openapi.OperationContex
 		contentType = mimeJSON
 	}
 
-	resp.Content[contentType] = MediaType{
-		Schema:        &oaiSchema,
-		Example:       nil,
-		Examples:      nil,
-		Encoding:      nil,
-		MapOfAnything: nil,
-	}
+	mt := resp.Content[contentType]
+	mt.Schema = &oaiSchema
+
+	resp.Content[contentType] = mt
 
 	if sch.Description != nil && resp.Description == "" {
 		resp.Description = *sch.Description
diff --git a/openapi31/reflect.go b/openapi31/reflect.go
index be9ac64..fc125b0 100644
--- a/openapi31/reflect.go
+++ b/openapi31/reflect.go
@@ -666,13 +666,10 @@ func (r *Reflector) parseJSONResponse(resp *Response, oc openapi.OperationContex
 		contentType = mimeJSON
 	}
 
-	resp.Content[contentType] = MediaType{
-		Schema:        sm,
-		Example:       nil,
-		Examples:      nil,
-		Encoding:      nil,
-		MapOfAnything: nil,
-	}
+	mt := resp.Content[contentType]
+	mt.Schema = sm
+
+	resp.Content[contentType] = mt
 
 	if sch.Description != nil && resp.Description == "" {
 		resp.Description = *sch.Description


Test patch:
diff --git a/openapi3/reflect_test.go b/openapi3/reflect_test.go
index 6b30525..dd2db25 100644
--- a/openapi3/reflect_test.go
+++ b/openapi3/reflect_test.go
@@ -1209,3 +1209,92 @@ func TestReflector_AddOperation_jsonschemaStruct(t *testing.T) {
 	  }
 	}`, r.SpecSchema())
 }
+
+func TestNewReflector_examples(t *testing.T) {
+	r := openapi3.NewReflector()
+
+	op, err := r.NewOperationContext(http.MethodGet, "/")
+	require.NoError(t, err)
+
+	type O1 struct {
+		F1   int    `json:"f1,omitempty"`
+		Code string `json:"code"`
+	}
+
+	type O2 struct {
+		F2   int    `json:"f2,omitempty"`
+		Code string `json:"code"`
+	}
+
+	st := http.StatusCreated
+
+	op.AddRespStructure(jsonschema.OneOf(O1{}, O2{}), func(cu *openapi.ContentUnit) {
+		cu.HTTPStatus = st
+	})
+
+	if o3, ok := op.(openapi3.OperationExposer); ok {
+		c := openapi3.MediaType{}
+		c.Examples = map[string]openapi3.ExampleOrRef{
+			"responseOne": {
+				Example: (&openapi3.Example{}).WithSummary("First possible answer").WithValue(O1{Code: "1234567890123456789012"}),
+			},
+			"responseTwo": {
+				Example: (&openapi3.Example{}).WithSummary("Other possible answer").WithValue(O2{Code: "0000000000000000000000"}),
+			},
+		}
+		resp := openapi3.Response{}
+		resp.WithContentItem("application/json", c)
+
+		o3.Operation().Responses.WithMapOfResponseOrRefValuesItem(strconv.Itoa(st), openapi3.ResponseOrRef{
+			Response: &resp,
+		})
+	}
+
+	require.NoError(t, r.AddOperation(op))
+	assertjson.EqMarshal(t, `{
+	  "openapi":"3.0.3","info":{"title":"","version":""},
+	  "paths":{
+		"/":{
+		  "get":{
+			"responses":{
+			  "201":{
+				"description":"Created",
+				"content":{
+				  "application/json":{
+					"schema":{
+					  "oneOf":[
+						{"$ref":"#/components/schemas/Openapi3TestO1"},
+						{"$ref":"#/components/schemas/Openapi3TestO2"}
+					  ]
+					},
+					"examples":{
+					  "responseOne":{
+						"summary":"First possible answer",
+						"value":{"code":"1234567890123456789012"}
+					  },
+					  "responseTwo":{
+						"summary":"Other possible answer",
+						"value":{"code":"0000000000000000000000"}
+					  }
+					}
+				  }
+				}
+			  }
+			}
+		  }
+		}
+	  },
+	  "components":{
+		"schemas":{
+		  "Openapi3TestO1":{
+			"type":"object",
+			"properties":{"code":{"type":"string"},"f1":{"type":"integer"}}
+		  },
+		  "Openapi3TestO2":{
+			"type":"object",
+			"properties":{"code":{"type":"string"},"f2":{"type":"integer"}}
+		  }
+		}
+	  }
+	}`, r.SpecSchema())
+}
diff --git a/openapi31/reflect_test.go b/openapi31/reflect_test.go
index 524e4df..be0b9e8 100644
--- a/openapi31/reflect_test.go
+++ b/openapi31/reflect_test.go
@@ -1337,3 +1337,92 @@ func TestReflector_AddOperation_jsonschemaStruct(t *testing.T) {
 	  }
 	}`, r.SpecSchema())
 }
+
+func TestNewReflector_examples(t *testing.T) {
+	r := openapi31.NewReflector()
+
+	op, err := r.NewOperationContext(http.MethodGet, "/")
+	require.NoError(t, err)
+
+	type O1 struct {
+		F1   int    `json:"f1,omitempty"`
+		Code string `json:"code"`
+	}
+
+	type O2 struct {
+		F2   int    `json:"f2,omitempty"`
+		Code string `json:"code"`
+	}
+
+	st := http.StatusCreated
+
+	op.AddRespStructure(jsonschema.OneOf(O1{}, O2{}), func(cu *openapi.ContentUnit) {
+		cu.HTTPStatus = st
+	})
+
+	if o3, ok := op.(openapi31.OperationExposer); ok {
+		c := openapi31.MediaType{}
+		c.Examples = map[string]openapi31.ExampleOrReference{
+			"responseOne": {
+				Example: (&openapi31.Example{}).WithSummary("First possible answer").WithValue(O1{Code: "1234567890123456789012"}),
+			},
+			"responseTwo": {
+				Example: (&openapi31.Example{}).WithSummary("Other possible answer").WithValue(O2{Code: "0000000000000000000000"}),
+			},
+		}
+		resp := openapi31.Response{}
+		resp.WithContentItem("application/json", c)
+
+		o3.Operation().ResponsesEns().WithMapOfResponseOrReferenceValuesItem(strconv.Itoa(st), openapi31.ResponseOrReference{
+			Response: &resp,
+		})
+	}
+
+	require.NoError(t, r.AddOperation(op))
+	assertjson.EqMarshal(t, `{
+	  "openapi":"3.1.0","info":{"title":"","version":""},
+	  "paths":{
+		"/":{
+		  "get":{
+			"responses":{
+			  "201":{
+				"description":"Created",
+				"content":{
+				  "application/json":{
+					"schema":{
+					  "oneOf":[
+						{"$ref":"#/components/schemas/Openapi31TestO1"},
+						{"$ref":"#/components/schemas/Openapi31TestO2"}
+					  ]
+					},
+					"examples":{
+					  "responseOne":{
+						"summary":"First possible answer",
+						"value":{"code":"1234567890123456789012"}
+					  },
+					  "responseTwo":{
+						"summary":"Other possible answer",
+						"value":{"code":"0000000000000000000000"}
+					  }
+					}
+				  }
+				}
+			  }
+			}
+		  }
+		}
+	  },
+	  "components":{
+		"schemas":{
+		  "Openapi31TestO1":{
+			"properties":{"code":{"type":"string"},"f1":{"type":"integer"}},
+			"type":"object"
+		  },
+		  "Openapi31TestO2":{
+			"properties":{"code":{"type":"string"},"f2":{"type":"integer"}},
+			"type":"object"
+		  }
+		}
+	  }
+	}`, r.SpecSchema())
+}