openapi-generator: [BUG] [Go] Missing support for additionalProperties in golang
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- What’s the version of OpenAPI Generator used?
- Have you search for related issues/PRs?
- What’s the actual output vs expected output?
- [Optional] Bounty to sponsor the fix (example)
Description
In the generated golang code, there is no support for open-ended list of additional properties. When a schema object includes the additionalProperties attribute, the generated golang code should have a way to store arbitrary key-value pairs. In golang this could be done using a map[string]interface{} or possibly a more specific type depending on the input YAML.
For example, given the AdditionalPropertiesAnyType type in petstore-with-fake-endpoints-models-for-testing.yaml, the code generator generates model_additional_properties_any_type.go. However, the generated struct does not have a way to store, marshal and unmarshal an arbitrary list of key value pairs.
One code generator that seems to properly handle “additionalProperties” is Java. Given the same input YAML OAS specification, the generated Java class extends from HashMap, which makes it possible to store arbitrary key, value pairs:
public class AdditionalPropertiesAnyType extends HashMap<String, Object>
openapi-generator version
master december 28 2019
OpenAPI declaration file content or url
AdditionalPropertiesAnyType:
type: object
properties:
name:
type: string
additionalProperties:
type: object
Command line used for generation
golang
Steps to reproduce
./bin/go-experimental-petstore.sh
./bin/openapi3/go-experimental-petstore.sh
Related issues/PRs
Support for additional properties in python: #2029 (though it seems this PR can be closed, Python-experimental already supports additionalProperties)
Golang “parent” problem identified while working on #4607
Suggest a fix
Unlike Java, golang does not support inheritance. One way to fix the problem in golang is to generate a struct field named “AdditionalProperties” which is of type map[string]interface{}. The specific type would be generated based on the actual OAS specification. Below is a struct that has a map[string]interface{}. Custom Marshal/Unmarshal functions are written to inline the JSON properties. Also, the unmarshaler would have to be improved to avoid duplicating key,value pairs. This is just an example to discuss a possible solution.
package main
import (
"encoding/json"
"fmt"
)
type Animal struct {
Color string `"json:color"`
AdditionalProperties map[string]interface{}
}
func (t *Animal) UnmarshalJSON(data []byte) error {
type t_ Animal
var a t_
_ = json.Unmarshal(data, &a)
*t = Animal(a)
_ = json.Unmarshal(data, &t.AdditionalProperties)
return nil
}
func main() {
b := []byte(`{"color": "brown", "type": "dog"}`)
var t Animal
_ = json.Unmarshal(b, &t)
fmt.Printf("Animal: %+v\n", t)
}
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 17 (12 by maintainers)
Ah ok. Now I see what you mean. When we first added the option
disallowAdditionalPropertiesIfNotPresent, we only supported true of false. In other worlds, our first implementation does not cover the case that additionalProperties is AnyType.