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)

Most upvoted comments

So I am not understanding why it must be only set to true instead of a free form object schema to achieve the same map?

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.