Parameters read from JSON with SchemaXORContent could not be marshalled back - duplicate keys
- 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