Skip to content

Commit 3d3330c

Browse files
committed
feat: exit early when failed to parse json spec
1 parent 1f17c50 commit 3d3330c

File tree

4 files changed

+46
-21
lines changed

4 files changed

+46
-21
lines changed

datamodel/spec_info.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,22 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
104104
_, openAPI2 := utils.FindKeyNode(utils.OpenApi2, parsedSpec.Content)
105105
_, asyncAPI := utils.FindKeyNode(utils.AsyncApi, parsedSpec.Content)
106106

107-
parseJSON := func(bytes []byte, spec *SpecInfo, parsedNode *yaml.Node) {
107+
parseJSON := func(bytes []byte, spec *SpecInfo, parsedNode *yaml.Node) error {
108108
var jsonSpec map[string]interface{}
109-
if utils.IsYAML(string(bytes)) {
109+
switch {
110+
case utils.IsYAML(string(bytes)):
110111
_ = parsedNode.Decode(&jsonSpec)
111112
b, _ := json.Marshal(&jsonSpec)
112113
spec.SpecJSONBytes = &b
113114
spec.SpecJSON = &jsonSpec
114-
} else {
115-
_ = json.Unmarshal(bytes, &jsonSpec)
115+
case utils.IsJSON(string(bytes)):
116+
if err := json.Unmarshal(bytes, &jsonSpec); err != nil {
117+
return err
118+
}
116119
spec.SpecJSONBytes = &bytes
117120
spec.SpecJSON = &jsonSpec
118121
}
122+
return nil
119123
}
120124

121125
// if !bypass {
@@ -149,7 +153,10 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
149153
}
150154

151155
// parse JSON
152-
parseJSON(spec, specInfo, &parsedSpec)
156+
if err := parseJSON(spec, specInfo, &parsedSpec); err != nil {
157+
specInfo.Error = fmt.Errorf("unable to parse specification: %w", err)
158+
return specInfo, specInfo.Error
159+
}
153160
parsed = true
154161

155162
// double check for the right version, people mix this up.
@@ -176,7 +183,10 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
176183
specInfo.APISchema = OpenAPI2SchemaData
177184

178185
// parse JSON
179-
parseJSON(spec, specInfo, &parsedSpec)
186+
if err := parseJSON(spec, specInfo, &parsedSpec); err != nil {
187+
specInfo.Error = fmt.Errorf("unable to parse specification: %w", err)
188+
return specInfo, specInfo.Error
189+
}
180190
parsed = true
181191

182192
// I am not certain this edge-case is very frequent, but let's make sure we handle it anyway.
@@ -200,7 +210,10 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
200210
// TODO: format for AsyncAPI.
201211

202212
// parse JSON
203-
parseJSON(spec, specInfo, &parsedSpec)
213+
if err := parseJSON(spec, specInfo, &parsedSpec); err != nil {
214+
specInfo.Error = fmt.Errorf("unable to parse specification: %w", err)
215+
return specInfo, nil
216+
}
204217
parsed = true
205218

206219
// so far there is only 2 as a major release of AsyncAPI
@@ -215,7 +228,10 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
215228
if specInfo.SpecType == "" {
216229
// parse JSON
217230
if !bypass {
218-
parseJSON(spec, specInfo, &parsedSpec)
231+
if err := parseJSON(spec, specInfo, &parsedSpec); err != nil {
232+
specInfo.Error = errors.New("spec type not supported by libopenapi, sorry")
233+
return specInfo, specInfo.Error
234+
}
219235
parsed = true
220236
specInfo.Error = errors.New("spec type not supported by libopenapi, sorry")
221237
return specInfo, specInfo.Error
@@ -227,7 +243,10 @@ func ExtractSpecInfoWithDocumentCheck(spec []byte, bypass bool) (*SpecInfo, erro
227243
//}
228244

229245
if !parsed {
230-
parseJSON(spec, specInfo, &parsedSpec)
246+
if err := parseJSON(spec, specInfo, &parsedSpec); err != nil {
247+
specInfo.Error = fmt.Errorf("unable to parse specification: %w", err)
248+
return specInfo, specInfo.Error
249+
}
231250
}
232251

233252
// detect the original whitespace indentation

datamodel/spec_info_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ const (
2424
)
2525

2626
var (
27-
goodJSON = `{"name":"kitty", "noises":["meow","purrrr","gggrrraaaaaooooww"]}`
28-
badJSON = `{"name":"kitty, "noises":[{"meow","purrrr","gggrrraaaaaooooww"]}}`
29-
goodYAML = `name: kitty
27+
goodJSON = `{"name":"kitty", "noises":["meow","purrrr","gggrrraaaaaooooww"]}`
28+
badJSON = `{"name":"kitty, "noises":[{"meow","purrrr","gggrrraaaaaooooww"]}}`
29+
badJSONContainingComma = `{"openapi":"3.0.3","info":{"title":"Broken API Spec","version":"1.0.0"},"paths":{"/ping":{"get":{"summary":"Ping endpoint","responses":{"200":{"description":"OK",}}}}}}`
30+
goodYAML = `name: kitty
3031
noises:
3132
- meow
3233
- purrr
@@ -118,6 +119,11 @@ func TestExtractSpecInfo_InvalidJSON(t *testing.T) {
118119
assert.Error(t, e)
119120
}
120121

122+
func TestExtractSpecInfo_InvalidJSONContainingExtraComma(t *testing.T) {
123+
_, e := ExtractSpecInfo([]byte(badJSONContainingComma))
124+
assert.EqualError(t, e, "unable to parse specification: invalid character '}' looking for beginning of object key string")
125+
}
126+
121127
func TestExtractSpecInfo_Nothing(t *testing.T) {
122128
_, e := ExtractSpecInfo([]byte(""))
123129
assert.Error(t, e)

document_examples_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,12 +378,12 @@ func TestExampleCompareDocuments_swagger(t *testing.T) {
378378
func TestDocument_Paths_As_Array(t *testing.T) {
379379
// paths can now be wrapped in an array.
380380
spec := `{
381-
"openapi": "3.1.0",
382-
"paths": [
383-
"/": {
384-
"get": {}
385-
}
386-
]
381+
"openapi": "3.1.0",
382+
"paths": {
383+
"/": {
384+
"get": {}
385+
}
386+
}
387387
}
388388
`
389389
// create a new document from specification bytes

document_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -544,9 +544,9 @@ func TestDocument_BuildModelBad(t *testing.T) {
544544
}
545545

546546
func TestDocument_Serialize_JSON_Modified(t *testing.T) {
547-
json := `{ 'openapi': '3.0',
548-
'info': {
549-
'title': 'The magic API'
547+
json := `{ "openapi": "3.0",
548+
"info": {
549+
"title": "The magic API"
550550
}
551551
}
552552
`

0 commit comments

Comments
 (0)