Repository: swaggest/openapi-go
Pull request #70 (2023-07-24 10:43:19)

Prefer less-known field tags to json when deciding on param content type

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

| Language  | Files |   Lines    | Code | Comments  | Blanks | Complexity |     Bytes     |
|-----------|-------|------------|------|-----------|--------|------------|---------------|
| Go        | 7     | 1329       | 995  | 64        | 270    | 307 (+1)   | 30.2K (+47B)  |
| Go (test) | 7     | 2033 (+10) | 1475 | 319 (+10) | 239    | 27         | 52.6K (+454B) |
<!-- Sticky Pull Request CommentLOC -->
github-actions[bot]: ### Go API Changes

<pre>
# summary
Inferred base version: v0.2.32
Suggested version: v0.2.33
</pre>
<!-- Sticky Pull Request Commentgorelease -->
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%   |

</details>

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

No changes in coverage.

</details>
<!-- Sticky Pull Request Commentunit-test -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/swaggest/openapi-go/pull/70?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) Report
> Merging [#70](https://app.codecov.io/gh/swaggest/openapi-go/pull/70?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) (7f93372) into [master](https://app.codecov.io/gh/swaggest/openapi-go/commit/8a71b2dcacac5ab217737d403e8607862f27da1b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=swaggest) (8a71b2d) will **not change** coverage.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##           master      #70   +/-   ##
=======================================
  Coverage   42.24%   42.24%           
=======================================
  Files           5        5           
  Lines        3589     3589           
=======================================
  Hits         1516     1516           
  Misses       1784     1784           
  Partials      289      289           
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `42.24% <100.00%> (ø)` | |

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/70?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/70?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%> (ø)` | |

: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 2ba52d9..e019503 100644
--- a/openapi3/reflect.go
+++ b/openapi3/reflect.go
@@ -309,7 +309,7 @@ func (r *Reflector) parseParametersIn(
 
 			// Check if parameter is an JSON encoded object.
 			property := reflect.New(field.Type).Interface()
-			if refl.HasTaggedFields(property, tagJSON) {
+			if refl.HasTaggedFields(property, tagJSON) && !refl.HasTaggedFields(property, string(in)) {
 				propertySchema, err := r.Reflect(property,
 					r.withOperation(oc, false, string(in)),
 					jsonschema.DefinitionsPrefix(definitionsPrefix),


Test patch:
diff --git a/openapi3/example_test.go b/openapi3/example_test.go
index 74f17b4..c113e8b 100644
--- a/openapi3/example_test.go
+++ b/openapi3/example_test.go
@@ -514,7 +514,7 @@ func ExampleReflector_SetRequest_queryObject() {
 		Quux   float64 `query:"quux"`
 		Deeper struct {
 			Val string `query:"val"`
-		} `json:"deeper"`
+		} `query:"deeper"`
 	}
 
 	type req struct {
@@ -559,12 +559,12 @@ func ExampleReflector_SetRequest_queryObject() {
 	//               $ref: '#/components/schemas/QueryOpenapi3TestJsonFilter'
 	//         in: query
 	//         name: json_filter
-	//       - content:
-	//           application/json:
-	//             schema:
-	//               $ref: '#/components/schemas/QueryOpenapi3TestDeepObjectFilter'
+	//       - explode: true
 	//         in: query
 	//         name: deep_object_filter
+	//         schema:
+	//           $ref: '#/components/schemas/QueryOpenapi3TestDeepObjectFilter'
+	//         style: deepObject
 	//       - in: path
 	//         name: id
 	//         required: true
@@ -578,9 +578,15 @@ func ExampleReflector_SetRequest_queryObject() {
 	//   schemas:
 	//     QueryOpenapi3TestDeepObjectFilter:
 	//       properties:
+	//         baz:
+	//           type: boolean
 	//         deeper:
-	//           nullable: true
+	//           properties:
+	//             val:
+	//               type: string
 	//           type: object
+	//         quux:
+	//           type: number
 	//       type: object
 	//     QueryOpenapi3TestJsonFilter:
 	//       properties:
diff --git a/openapi3/reflect_test.go b/openapi3/reflect_test.go
index b3021fc..e44aeda 100644
--- a/openapi3/reflect_test.go
+++ b/openapi3/reflect_test.go
@@ -878,6 +878,8 @@ func TestReflector_SetupRequest_form_only(t *testing.T) {
 func TestReflector_SetRequest_queryObject(t *testing.T) {
 	reflector := openapi3.Reflector{}
 
+	// JSON object is only enabled when at least one `json` tag is available on top-level property,
+	// and there are no `in` tags, e.g. `query`.
 	type jsonFilter struct {
 		Foo    string `json:"foo"`
 		Bar    int    `json:"bar"`
@@ -886,9 +888,11 @@ func TestReflector_SetRequest_queryObject(t *testing.T) {
 		} `json:"deeper"`
 	}
 
+	// Deep object structure may have `json` tags, they are ignored in presence of
+	// at least one top-level field with a matching `in` tag, e.g. `query`.
 	type deepObjectFilter struct {
-		Baz    bool    `query:"baz"`
-		Quux   float64 `query:"quux"`
+		Baz    bool    `json:"baz" query:"baz"`
+		Quux   float64 `json:"quux" query:"quux"`
 		Deeper struct {
 			Val string `query:"val"`
 		} `query:"deeper"`