Repository: getkin/kin-openapi (go)

Issue:
openapi2conv does not respect "produces" keyword
It seems like when using `openapi2conv.ToV3`, the result content-type is always JSON. Please see the [example](https://goplay.tools/snippet/qeaIZN5khfd) (also pasted below). The output is `application/json` while the `produces` field is `application/toml`.

I guess that this is because that hard-coded "WithJsonSchemaRef" here: https://github.com/getkin/kin-openapi/blob/master/openapi2conv/openapi2_conv.go#L426 or somewhere in this area.

Hope I'm correctly defining a content-type for response in openapi v2, and using openapi2conv correctly as well.

Thanks.

---

```go
package main

import (
	"fmt"

	"github.com/getkin/kin-openapi/openapi2"
	"github.com/getkin/kin-openapi/openapi2conv"
	"github.com/getkin/kin-openapi/openapi3"
	"github.com/invopop/yaml"
)

func v2v3YAML(spec2 []byte) (doc3 *openapi3.T, err error) {
	var doc2 openapi2.T
	if err = yaml.Unmarshal(spec2, &doc2); err != nil {
		return
	}
	doc3, err = openapi2conv.ToV3(&doc2)
	return
}

func main() {
	spec := []byte(`paths:
  /ping:
    get:
      produces:
        - application/toml
      responses:
        200:
          schema:
            type: object
            properties:
              username:
                type: string
                description: The user name.`)

	v3, err := v2v3YAML(spec)
	if err != nil {
		panic(err)
	}

	yamlV3, err := yaml.Marshal(v3)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(yamlV3))
}
```

Got:
```yaml
components: {}
info:
    title: ""
    version: ""
openapi: 3.0.3
paths:
    /ping:
        get:
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    username:
                                        description: The user name.
                                        type: string
                                type: object
                    description: ""

```

Expected:
```yaml
components: {}
info:
    title: ""
    version: ""
openapi: 3.0.3
paths:
    /ping:
        get:
            responses:
                "200":
                    content:
                        application/toml:
                            schema:
                                properties:
                                    username:
                                        description: The user name.
                                        type: string
                                type: object
                    description: ""
```

Pull request:
fix: openapi2conv respects produces field
Closes #573 
---

`ToV3Response` now accepts the content of the "produces" field and creates the responses with the right content-type.

Patch:
diff --git a/openapi2conv/openapi2_conv.go b/openapi2conv/openapi2_conv.go
index d34dd31..53b4b40 100644
--- a/openapi2conv/openapi2_conv.go
+++ b/openapi2conv/openapi2_conv.go
@@ -84,7 +84,7 @@ func ToV3(doc2 *openapi2.T) (*openapi3.T, error) {
 	if responses := doc2.Responses; len(responses) != 0 {
 		doc3.Components.Responses = make(map[string]*openapi3.ResponseRef, len(responses))
 		for k, response := range responses {
-			r, err := ToV3Response(response)
+			r, err := ToV3Response(response, doc2.Produces)
 			if err != nil {
 				return nil, err
 			}
@@ -193,7 +193,7 @@ func ToV3Operation(doc2 *openapi2.T, components *openapi3.Components, pathItem *
 	if responses := operation.Responses; responses != nil {
 		doc3Responses := make(openapi3.Responses, len(responses))
 		for k, response := range responses {
-			doc3, err := ToV3Response(response)
+			doc3, err := ToV3Response(response, operation.Produces)
 			if err != nil {
 				return nil, err
 			}
@@ -413,7 +413,7 @@ func onlyOneReqBodyParam(bodies []*openapi3.RequestBodyRef, formDataSchemas map[
 	return nil, nil
 }
 
-func ToV3Response(response *openapi2.Response) (*openapi3.ResponseRef, error) {
+func ToV3Response(response *openapi2.Response, produces []string) (*openapi3.ResponseRef, error) {
 	if ref := response.Ref; ref != "" {
 		return &openapi3.ResponseRef{Ref: ToV3Ref(ref)}, nil
 	}
@@ -422,8 +422,18 @@ func ToV3Response(response *openapi2.Response) (*openapi3.ResponseRef, error) {
 		Description:    &response.Description,
 		ExtensionProps: response.ExtensionProps,
 	}
+
+	// Default to "application/json" if "produces" is not specified.
+	if len(produces) == 0 {
+		produces = []string{"application/json"}
+	}
+
 	if schemaRef := response.Schema; schemaRef != nil {
-		result.WithJSONSchemaRef(ToV3SchemaRef(schemaRef))
+		schema := ToV3SchemaRef(schemaRef)
+		result.Content = make(openapi3.Content, len(produces))
+		for _, mime := range produces {
+			result.Content[mime] = openapi3.NewMediaType().WithSchemaRef(schema)
+		}
 	}
 	if headers := response.Headers; len(headers) > 0 {
 		result.Headers = ToV3Headers(headers)


Test patch:
diff --git a/openapi2conv/issue573_test.go b/openapi2conv/issue573_test.go
new file mode 100644
index 0000000..cefac40
--- /dev/null
+++ b/openapi2conv/issue573_test.go
@@ -0,0 +1,48 @@
+package openapi2conv
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestIssue573(t *testing.T) {
+	spec := []byte(`paths:
+  /ping:
+    get:
+      produces:
+        - application/toml
+        - application/xml
+      responses:
+        200:
+          schema:
+            type: object
+            properties:
+              username:
+                type: string
+                description: The user name.
+    post:
+      responses:
+        200:
+          schema:
+            type: object
+            properties:
+              username:
+                type: string
+                description: The user name.`)
+
+	v3, err := v2v3YAML(spec)
+	require.NoError(t, err)
+
+	// Make sure the response content appears for each mime-type originally
+	// appeared in "produces".
+	pingGetContent := v3.Paths["/ping"].Get.Responses["200"].Value.Content
+	require.Len(t, pingGetContent, 2)
+	require.Contains(t, pingGetContent, "application/toml")
+	require.Contains(t, pingGetContent, "application/xml")
+
+	// Is "produces" is not explicitly specified, default to "application/json".
+	pingPostContent := v3.Paths["/ping"].Post.Responses["200"].Value.Content
+	require.Len(t, pingPostContent, 1)
+	require.Contains(t, pingPostContent, "application/json")
+}