Repository: swaggest/openapi-go
Pull request #69 (2023-07-23 17:09:20)

Use separate definitions for param schemas

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

| Language  | Files |   Lines   |   Code    | Comments |  Blanks  | Complexity |     Bytes     |
|-----------|-------|-----------|-----------|----------|----------|------------|---------------|
| Go        | 7     | 1329 (+7) | 995 (+5)  | 64       | 270 (+2) | 306        | 30.1K (+244B) |
| Go (test) | 7     | 2023 (+6) | 1475 (+6) | 309      | 239      | 27         | 52.2K (+113B) |
| JSON      | 6     | 2212 (+1) | 2212 (+1) | 0        | 0        | 0          | 50.3K (+110B) |
<!-- Sticky Pull Request CommentLOC -->
github-actions[bot]: ### Unit Test Coverage
total:								(statements)				49.9%
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:250 | parseParametersIn | 100.0%   |
| openapi3/reflect.go:380 | collectDefinition | 100.0%   |
| openapi3/reflect.go:552 | parseJSONResponse | 100.0%   |

</details>

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

|                        File                        |     Function      | Base Coverage | Current Coverage |
|----------------------------------------------------|-------------------|---------------|------------------|
| Total                                              |                   | 49.8%         | 49.9% (+0.1%)    |
| github.com/swaggest/openapi-go/openapi3/reflect.go | parseParametersIn | 85.7%         | 86.2% (+0.5%)    |

</details>
<!-- Sticky Pull Request Commentunit-test -->
github-actions[bot]: ### Go API Changes

<pre>
# summary
Inferred base version: v0.2.31
Suggested version: v0.2.32
</pre>
<!-- Sticky Pull Request Commentgorelease -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/swaggest/openapi-go/pull/69?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) Report
> Merging [#69](https://app.codecov.io/gh/swaggest/openapi-go/pull/69?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) (a31a758) into [master](https://app.codecov.io/gh/swaggest/openapi-go/commit/c45b01416e6dfde09e940ce012a1fdab3bc9f47e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) (c45b014) will **increase** coverage by `0.06%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master      #69      +/-   ##
==========================================
+ Coverage   42.17%   42.24%   +0.06%     
==========================================
  Files           5        5              
  Lines        3585     3589       +4     
==========================================
+ Hits         1512     1516       +4     
  Misses       1784     1784              
  Partials      289      289              
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `42.24% <100.00%> (+0.06%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://app.codecov.io/gh/swaggest/openapi-go/pull/69?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) | Coverage Δ | |
|---|---|---|
| [openapi3/reflect.go](https://app.codecov.io/gh/swaggest/openapi-go/pull/69?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest#diff-b3BlbmFwaTMvcmVmbGVjdC5nbw==) | `87.08% <100.00%> (+0.17%)` | :arrow_up: |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest)


Patch:
diff --git a/openapi3/reflect.go b/openapi3/reflect.go
index 73cf2bf..2ba52d9 100644
--- a/openapi3/reflect.go
+++ b/openapi3/reflect.go
@@ -257,10 +257,13 @@ func (r *Reflector) parseParametersIn(
 		return nil
 	}
 
+	defNamePrefix := strings.Title(string(in))
+	definitionsPrefix := "#/components/schemas/" + defNamePrefix
+
 	s, err := r.Reflect(input,
 		r.withOperation(oc, false, string(in)),
-		jsonschema.DefinitionsPrefix("#/components/schemas/"),
-		jsonschema.CollectDefinitions(r.collectDefinition),
+		jsonschema.DefinitionsPrefix(definitionsPrefix),
+		jsonschema.CollectDefinitions(r.collectDefinition(defNamePrefix)),
 		jsonschema.PropertyNameMapping(propertyMapping),
 		jsonschema.PropertyNameTag(string(in), additionalTags...),
 		func(rc *jsonschema.ReflectContext) {
@@ -309,8 +312,8 @@ func (r *Reflector) parseParametersIn(
 			if refl.HasTaggedFields(property, tagJSON) {
 				propertySchema, err := r.Reflect(property,
 					r.withOperation(oc, false, string(in)),
-					jsonschema.DefinitionsPrefix("#/components/schemas/"),
-					jsonschema.CollectDefinitions(r.collectDefinition),
+					jsonschema.DefinitionsPrefix(definitionsPrefix),
+					jsonschema.CollectDefinitions(r.collectDefinition(defNamePrefix)),
 					jsonschema.RootRef,
 				)
 				if err != nil {
@@ -374,15 +377,19 @@ func (r *Reflector) parseParametersIn(
 	return nil
 }
 
-func (r *Reflector) collectDefinition(name string, schema jsonschema.Schema) {
-	if _, exists := r.SpecEns().ComponentsEns().SchemasEns().MapOfSchemaOrRefValues[name]; exists {
-		return
-	}
+func (r *Reflector) collectDefinition(namePrefix string) func(name string, schema jsonschema.Schema) {
+	return func(name string, schema jsonschema.Schema) {
+		name = namePrefix + name
 
-	s := SchemaOrRef{}
-	s.FromJSONSchema(schema.ToSchemaOrBool())
+		if _, exists := r.SpecEns().ComponentsEns().SchemasEns().MapOfSchemaOrRefValues[name]; exists {
+			return
+		}
 
-	r.SpecEns().ComponentsEns().SchemasEns().WithMapOfSchemaOrRefValuesItem(name, s)
+		s := SchemaOrRef{}
+		s.FromJSONSchema(schema.ToSchemaOrBool())
+
+		r.SpecEns().ComponentsEns().SchemasEns().WithMapOfSchemaOrRefValuesItem(name, s)
+	}
 }
 
 func (r *Reflector) parseResponseHeader(resp *Response, oc OperationContext) error {
@@ -555,7 +562,7 @@ func (r *Reflector) parseJSONResponse(resp *Response, oc OperationContext) error
 		r.withOperation(oc, true, "body"),
 		jsonschema.RootRef,
 		jsonschema.DefinitionsPrefix("#/components/schemas/"),
-		jsonschema.CollectDefinitions(r.collectDefinition),
+		jsonschema.CollectDefinitions(r.collectDefinition("")),
 	)
 	if err != nil {
 		return err


Test patch:
diff --git a/openapi3/_testdata/openapi.json b/openapi3/_testdata/openapi.json
index cf404f9..5140cba 100644
--- a/openapi3/_testdata/openapi.json
+++ b/openapi3/_testdata/openapi.json
@@ -60,7 +60,7 @@
      {"name":"in_path","in":"path","required":true,"schema":{"type":"integer"}},
      {"name":"in_cookie","in":"cookie","deprecated":true,"schema":{"type":"string","deprecated":true}},
      {"name":"in_header","in":"header","schema":{"type":"number"}},
-     {"name":"uuid","in":"header","schema":{"$ref":"#/components/schemas/Openapi3TestUUID"}}
+     {"name":"uuid","in":"header","schema":{"$ref":"#/components/schemas/HeaderOpenapi3TestUUID"}}
     ],
     "requestBody":{
      "content":{
@@ -108,6 +108,7 @@
      "upload2":{"$ref":"#/components/schemas/FormDataMultipartFileHeader"}
     }
    },
+   "HeaderOpenapi3TestUUID":{"type":"array","items":{"minimum":0,"type":"integer"},"nullable":true},
    "Openapi3TestReq":{"type":"object","properties":{"in_body1":{"type":"integer"},"in_body2":{"type":"string"}}},
    "Openapi3TestResp":{
     "title":"Sample Response","type":"object",
@@ -129,4 +130,4 @@
    "Openapi3TestUUID":{"type":"array","items":{"minimum":0,"type":"integer"},"nullable":true}
   }
  }
-}
\ No newline at end of file
+}
diff --git a/openapi3/_testdata/openapi_req.json b/openapi3/_testdata/openapi_req.json
index 3abe0bb..9b5ba10 100644
--- a/openapi3/_testdata/openapi_req.json
+++ b/openapi3/_testdata/openapi_req.json
@@ -20,4 +20,4 @@
    }
   }
  }
-}
\ No newline at end of file
+}
diff --git a/openapi3/_testdata/resp_schema.json b/openapi3/_testdata/resp_schema.json
index 0363f6a..24156a5 100644
--- a/openapi3/_testdata/resp_schema.json
+++ b/openapi3/_testdata/resp_schema.json
@@ -23,4 +23,4 @@
       "Openapi3TestUUID":{"items":{"minimum":0,"type":"integer"},"type":["array","null"]}
     }
   }
-}
\ No newline at end of file
+}
diff --git a/openapi3/example_test.go b/openapi3/example_test.go
index 382fe41..74f17b4 100644
--- a/openapi3/example_test.go
+++ b/openapi3/example_test.go
@@ -556,13 +556,13 @@ func ExampleReflector_SetRequest_queryObject() {
 	//       - content:
 	//           application/json:
 	//             schema:
-	//               $ref: '#/components/schemas/Openapi3TestJsonFilter'
+	//               $ref: '#/components/schemas/QueryOpenapi3TestJsonFilter'
 	//         in: query
 	//         name: json_filter
 	//       - content:
 	//           application/json:
 	//             schema:
-	//               $ref: '#/components/schemas/Openapi3TestDeepObjectFilter'
+	//               $ref: '#/components/schemas/QueryOpenapi3TestDeepObjectFilter'
 	//         in: query
 	//         name: deep_object_filter
 	//       - in: path
@@ -576,13 +576,13 @@ func ExampleReflector_SetRequest_queryObject() {
 	//           description: No Content
 	// components:
 	//   schemas:
-	//     Openapi3TestDeepObjectFilter:
+	//     QueryOpenapi3TestDeepObjectFilter:
 	//       properties:
 	//         deeper:
 	//           nullable: true
 	//           type: object
 	//       type: object
-	//     Openapi3TestJsonFilter:
+	//     QueryOpenapi3TestJsonFilter:
 	//       properties:
 	//         bar:
 	//           type: integer
diff --git a/openapi3/reflect_test.go b/openapi3/reflect_test.go
index 845dc85..b3021fc 100644
--- a/openapi3/reflect_test.go
+++ b/openapi3/reflect_test.go
@@ -486,26 +486,28 @@ func TestReflector_SetupRequest_queryNamedObject(t *testing.T) {
 	require.NoError(t, s.AddOperation(http.MethodPost, "/somewhere", op))
 
 	assertjson.EqMarshal(t, `{
-	 "openapi":"3.0.3","info":{"title":"SampleAPI","version":"1.2.3"},
-	 "paths":{
-	  "/somewhere":{
-	   "post":{
-		"parameters":[
-		 {
-		  "name":"in_query","in":"query","style":"deepObject","explode":true,
-		  "schema":{"$ref":"#/components/schemas/Openapi3TestLabels"}
-		 }
-		],
-		"responses":{"204":{"description":"No Content"}}
-	   }
+	  "openapi":"3.0.3","info":{"title":"SampleAPI","version":"1.2.3"},
+	  "paths":{
+		"/somewhere":{
+		  "post":{
+			"parameters":[
+			  {
+				"name":"in_query","in":"query","style":"deepObject","explode":true,
+				"schema":{"$ref":"#/components/schemas/QueryOpenapi3TestLabels"}
+			  }
+			],
+			"responses":{"204":{"description":"No Content"}}
+		  }
+		}
+	  },
+	  "components":{
+		"schemas":{
+		  "QueryOpenapi3TestLabels":{"type":"object","additionalProperties":{"type":"number"}}
+		}
 	  }
-	 },
-	 "components":{
-	  "schemas":{"Openapi3TestLabels":{"type":"object","additionalProperties":{"type":"number"}}}
-	 }
 	}`, s)
 
-	js, found := reflector.ResolveJSONSchemaRef("#/components/schemas/Openapi3TestLabels")
+	js, found := reflector.ResolveJSONSchemaRef("#/components/schemas/QueryOpenapi3TestLabels")
 	assert.True(t, found)
 	assertjson.EqMarshal(t, `{"type":"object","additionalProperties":{"type":"number"}}`, js)
 }
@@ -540,13 +542,17 @@ func TestReflector_SetupRequest_jsonQuery(t *testing.T) {
 			  {
 				"name":"one","in":"query",
 				"content":{
-				  "application/json":{"schema":{"$ref":"#/components/schemas/Openapi3TestFilter"}}
+				  "application/json":{
+					"schema":{"$ref":"#/components/schemas/QueryOpenapi3TestFilter"}
+				  }
 				}
 			  },
 			  {
 				"name":"two","in":"query",
 				"content":{
-				  "application/json":{"schema":{"$ref":"#/components/schemas/Openapi3TestFilter"}}
+				  "application/json":{
+					"schema":{"$ref":"#/components/schemas/QueryOpenapi3TestFilter"}
+				  }
 				}
 			  },
 			  {
@@ -560,7 +566,7 @@ func TestReflector_SetupRequest_jsonQuery(t *testing.T) {
 	  },
 	  "components":{
 		"schemas":{
-		  "Openapi3TestFilter":{
+		  "QueryOpenapi3TestFilter":{
 			"type":"object",
 			"properties":{
 			  "labels":{"type":"array","items":{"type":"string"}},
@@ -930,14 +936,14 @@ func TestReflector_SetRequest_queryObject(t *testing.T) {
 				"name":"json_filter","in":"query",
 				"content":{
 				  "application/json":{
-					"schema":{"$ref":"#/components/schemas/Openapi3TestJsonFilter"}
+					"schema":{"$ref":"#/components/schemas/QueryOpenapi3TestJsonFilter"}
 				  }
 				}
 			  },
 			  {
 				"name":"deep_object_filter","in":"query","style":"deepObject",
 				"explode":true,
-				"schema":{"$ref":"#/components/schemas/Openapi3TestDeepObjectFilter"}
+				"schema":{"$ref":"#/components/schemas/QueryOpenapi3TestDeepObjectFilter"}
 			  },
 			  {
 				"name":"id","in":"path","required":true,
@@ -950,7 +956,7 @@ func TestReflector_SetRequest_queryObject(t *testing.T) {
 	  },
 	  "components":{
 		"schemas":{
-		  "Openapi3TestDeepObjectFilter":{
+		  "QueryOpenapi3TestDeepObjectFilter":{
 			"type":"object",
 			"properties":{
 			  "baz":{"type":"boolean"},
@@ -958,7 +964,7 @@ func TestReflector_SetRequest_queryObject(t *testing.T) {
 			  "quux":{"type":"number"}
 			}
 		  },
-		  "Openapi3TestJsonFilter":{
+		  "QueryOpenapi3TestJsonFilter":{
 			"type":"object",
 			"properties":{
 			  "bar":{"type":"integer"},