oapi-codegen
oapi-codegen copied to clipboard
additionalProperties and OneOf at the same time
The following spec:
openapi: 3.0.1
info:
title: OpenAPI-CodeGen Test
description: 'This is a test OpenAPI Spec'
version: 1.0.0
servers:
- url: https://test.oapi-codegen.com/v2
- url: http://test.oapi-codegen.com/v2
paths:
/cat:
get:
tags:
- cat
summary: Get cat status
operationId: getCatStatus
responses:
200:
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/Cat'
components:
schemas:
Cat:
additionalProperties: true
discriminator:
mapping:
alive: '#/components/schemas/CatAlive'
dead: '#/components/schemas/CatDead'
propertyName: state
oneOf:
- $ref: '#/components/schemas/CatAlive'
- $ref: '#/components/schemas/CatDead'
CatAlive:
properties:
state:
type: string
enum: [alive]
name:
type: string
alive_since:
type: string
format: date-time
required:
- state
CatDead:
properties:
state:
type: string
enum: [dead]
name:
type: string
dead_since:
type: string
format: date-time
cause:
type: string
enum: [car, dog, oldage, quantum-experiment]
required:
- state
Generates invalid code, because both the additionalProperties and the OneOf logic both generates a separate implementation of MarshallJSON and UnmarshallJSON, eg:
// Override default JSON handling for Cat to handle AdditionalProperties
func (a *Cat) UnmarshalJSON(b []byte) error {
object := make(map[string]json.RawMessage)
err := json.Unmarshal(b, &object)
if err != nil {
return err
}
if len(object) != 0 {
a.AdditionalProperties = make(map[string]interface{})
for fieldName, fieldBuf := range object {
var fieldVal interface{}
err := json.Unmarshal(fieldBuf, &fieldVal)
if err != nil {
return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
}
a.AdditionalProperties[fieldName] = fieldVal
}
}
return nil
}
vs
func (t *Cat) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
Is this case supposed to be supported? I didn't find a clear statement of open-api spec saying that yes, this case is positively supported, but https://editor.swagger.io seems to understand it:
However, one can work around this by setting additionalProperties on the individual oneOf elements, so maybe it isn't that high-priority overall.
I've prepared a potential fix: https://github.com/deepmap/oapi-codegen/pull/765