Skip to content

Commit 8e92e88

Browse files
committed
fix: issue unmarshalling when discriminator field is set in openapi2.0
1 parent c606b55 commit 8e92e88

File tree

4 files changed

+236
-4
lines changed

4 files changed

+236
-4
lines changed

openapi2/issues1010_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package openapi2
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestIssue1010(t *testing.T) {
11+
v2 := []byte(`
12+
{
13+
"basePath": "/v2",
14+
"host": "test.example.com",
15+
"info": {
16+
"title": "MyAPI",
17+
"version": "0.1",
18+
"x-info": "info extension"
19+
},
20+
"paths": {
21+
"/foo": {
22+
"get": {
23+
"operationId": "getFoo",
24+
"responses": {
25+
"200": {
26+
"description": "returns all information",
27+
"schema": {
28+
"$ref": "#/definitions/Pet"
29+
}
30+
},
31+
"default": {
32+
"description": "OK"
33+
}
34+
},
35+
"summary": "get foo"
36+
}
37+
}
38+
},
39+
"schemes": [
40+
"http"
41+
],
42+
"swagger": "2.0",
43+
"definitions": {
44+
"Pet": {
45+
"type": "object",
46+
"required": ["petType"],
47+
"properties": {
48+
"petType": {
49+
"type": "string"
50+
},
51+
"name": {
52+
"type": "string"
53+
},
54+
"age": {
55+
"type": "integer"
56+
}
57+
},
58+
"discriminator": "petType"
59+
},
60+
"Dog": {
61+
"allOf": [
62+
{
63+
"$ref": "#/definitions/Pet"
64+
},
65+
{
66+
"type": "object",
67+
"properties": {
68+
"breed": {
69+
"type": "string"
70+
}
71+
}
72+
}
73+
]
74+
},
75+
"Cat": {
76+
"allOf": [
77+
{
78+
"$ref": "#/definitions/Pet"
79+
},
80+
{
81+
"type": "object",
82+
"properties": {
83+
"color": {
84+
"type": "string"
85+
}
86+
}
87+
}
88+
]
89+
}
90+
}
91+
}
92+
`)
93+
94+
var doc2 T
95+
err := json.Unmarshal(v2, &doc2)
96+
require.NoError(t, err)
97+
}

openapi2/issuexxx_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package openapi2
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestIssue979(t *testing.T) {
11+
v2 := []byte(`
12+
{
13+
"basePath": "/v2",
14+
"host": "test.example.com",
15+
"info": {
16+
"title": "MyAPI",
17+
"version": "0.1",
18+
"x-info": "info extension"
19+
},
20+
"paths": {
21+
"/foo": {
22+
"get": {
23+
"operationId": "getFoo",
24+
"responses": {
25+
"200": {
26+
"description": "returns all information",
27+
"schema": {
28+
"$ref": "#/definitions/Pet"
29+
}
30+
},
31+
"default": {
32+
"description": "OK"
33+
}
34+
},
35+
"summary": "get foo"
36+
}
37+
}
38+
},
39+
"schemes": [
40+
"http"
41+
],
42+
"swagger": "2.0",
43+
"definitions": {
44+
"Pet": {
45+
"type": "object",
46+
"required": ["petType"],
47+
"properties": {
48+
"petType": {
49+
"type": "string"
50+
},
51+
"name": {
52+
"type": "string"
53+
},
54+
"age": {
55+
"type": "integer"
56+
}
57+
},
58+
"discriminator": "petType"
59+
},
60+
"Dog": {
61+
"allOf": [
62+
{
63+
"$ref": "#/definitions/Pet"
64+
},
65+
{
66+
"type": "object",
67+
"properties": {
68+
"breed": {
69+
"type": "string"
70+
}
71+
}
72+
}
73+
]
74+
},
75+
"Cat": {
76+
"allOf": [
77+
{
78+
"$ref": "#/definitions/Pet"
79+
},
80+
{
81+
"type": "object",
82+
"properties": {
83+
"color": {
84+
"type": "string"
85+
}
86+
}
87+
}
88+
]
89+
}
90+
}
91+
}
92+
`)
93+
94+
var doc2 T
95+
err := json.Unmarshal(v2, &doc2)
96+
require.NoError(t, err)
97+
}

openapi3/discriminator_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package openapi3
22

33
import (
4+
"encoding/json"
45
"testing"
56

67
"github.com/stretchr/testify/require"
@@ -52,5 +53,15 @@ func TestParsingDiscriminator(t *testing.T) {
5253
err = doc.Validate(loader.Context)
5354
require.NoError(t, err)
5455

55-
require.Len(t, doc.Components.Schemas["MyResponseType"].Value.Discriminator.Mapping, 2)
56+
discriminatorMap, ok := doc.Components.Schemas["MyResponseType"].Value.Discriminator.(map[string]interface{})
57+
require.True(t, ok)
58+
59+
discriminatorBytes, err := json.Marshal(discriminatorMap)
60+
require.NoError(t, err)
61+
62+
var discriminator *Discriminator
63+
err = json.Unmarshal(discriminatorBytes, &discriminator)
64+
require.NoError(t, err)
65+
66+
require.Len(t, discriminator.Mapping, 2)
5667
}

openapi3/schema.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ type Schema struct {
129129
MinProps uint64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
130130
MaxProps *uint64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
131131
AdditionalProperties AdditionalProperties `json:"additionalProperties,omitempty" yaml:"additionalProperties,omitempty"`
132-
Discriminator *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
132+
Discriminator interface{} `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
133133
}
134134

135135
type Types []string
@@ -1298,7 +1298,33 @@ func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, val
12981298
if v := schema.OneOf; len(v) > 0 {
12991299
var discriminatorRef string
13001300
if schema.Discriminator != nil {
1301-
pn := schema.Discriminator.PropertyName
1301+
var discriminator *Discriminator
1302+
if descriminatorValuemap, okcheck := schema.Discriminator.(map[string]any); okcheck {
1303+
marshaledDiscriminator, err := json.Marshal(descriminatorValuemap)
1304+
if err != nil {
1305+
return &SchemaError{
1306+
Schema: schema,
1307+
SchemaField: "discriminator",
1308+
Reason: fmt.Sprintf("unable to marshal the discriminator field in schema: %v", err),
1309+
}, false
1310+
}
1311+
1312+
if err := json.Unmarshal(marshaledDiscriminator, &discriminator); err != nil {
1313+
return &SchemaError{
1314+
Schema: schema,
1315+
SchemaField: "discriminator",
1316+
Reason: fmt.Sprintf("unable to unmarshall the discriminator field in schema: %v", err),
1317+
}, false
1318+
}
1319+
} else {
1320+
return &SchemaError{
1321+
Schema: schema,
1322+
SchemaField: "discriminator",
1323+
Reason: fmt.Sprintf("discriminator is expected to be an object, but received an unknown type"),
1324+
}, false
1325+
}
1326+
1327+
pn := discriminator.PropertyName
13021328
if valuemap, okcheck := value.(map[string]any); okcheck {
13031329
discriminatorVal, okcheck := valuemap[pn]
13041330
if !okcheck {
@@ -1319,7 +1345,7 @@ func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, val
13191345
}, false
13201346
}
13211347

1322-
if discriminatorRef, okcheck = schema.Discriminator.Mapping[discriminatorValString]; len(schema.Discriminator.Mapping) > 0 && !okcheck {
1348+
if discriminatorRef, okcheck = discriminator.Mapping[discriminatorValString]; len(discriminator.Mapping) > 0 && !okcheck {
13231349
return &SchemaError{
13241350
Value: discriminatorVal,
13251351
Schema: schema,
@@ -1328,6 +1354,7 @@ func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, val
13281354
}, false
13291355
}
13301356
}
1357+
13311358
}
13321359

13331360
var (

0 commit comments

Comments
 (0)