invopop / invopop/jsonschema

Parameters read from JSON with SchemaXORContent could not be marshalled back - duplicate keys

Open
#142 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
952
Forks
136
PR merge metrics
No merged PRs in 30d

Description

Have scenario
1. read `_base.json` as template of spec
2. update it
3. save as `api.json`

Got problem with parameters if they read from `_base.json`

1. Minimal schema to reproduce

```json
{
"openapi": "3.1.0",
"paths": {
"/": {
"get": {
"parameters": [
{
"name": "p",
"schema": {
"type": "string"
},
"in": "query"
}
]
}
}
}
}
```

5. Read it

```go
var spec *openapi3.Spec
if err = json.Unmarshal(errs.Must(os.ReadFile("./doc/api/_base.json")),&spec); err != nil { panic(err) }
```

6. Try write it back

```go
j, err = json.MarshalIndent(spec, "", " ")
if err != nil { panic(err) }
fmt.Println(string(j))
```
will produce
```json
{
"openapi": "3.1.0",
"paths": {
"/": {
"get": {
"parameters": [
{
"name": "p",
"schema": {
"type": "string"
},
"in": "query",
"schema": {
"type": "string"
},
"in": "query"
}
]
}
}
}
}
```

7. The problem is - the combination of `Parameter.SchemaXORContent`,`Parameter.Location` and `unionMarshal`

SchemaXORContent is used during unmarshal as buffer, and then used back in marshalling but without any key control of
unique in unionMarhal

8. Avoid -

For our case i have added

```go
func ReadSpecForUpdate(data []byte) (*openapi3.Spec, error) {
var spec *openapi3.Spec
if err := json.Unmarshal(data,&spec); err != nil { return nil, err }
for _, path := range spec.Paths.MapOfPathItemValues {
for _, op := range path.MapOfOperationValues {
for _, p := range op.Parameters {
// todo - some information could be lost ???
p.Parameter.SchemaXORContent = nil
p.Parameter.Location = nil
}
}
}
return spec, nil
}
```

9. Suggestion - rewrite `unionMarshal` - prepare data to avoid twice - pre merge data

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the round trip with the minimal OpenAPI JSON and inspect Parameter.SchemaXORContent, Parameter.Location, and unionMarshal during unmarshalling and marshalling. Done means json.MarshalIndent emits each parameter key only once while preserving the schema and location data.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.