oapi-codegenでHash Map  (additionalProperties) はどうexportされるか



Go言語で Open API 3.0対応の型情報を生成するとき、
[github.com/deepmap/oapi-codegen](https://github.com/deepmap/oapi-codegen)
を使ってます。
  
あまりユースケースとしてやりませんが、マップを表現したい時があると思います。
Dictionaries/HashMaps の仕様はこれです。
[Dictionaries, HashMaps and Associative Arrays](https://swagger.io/docs/specification/data-models/dictionaries/)

oapi-codegenの公式のReadmeでは、additionalPropertiesに関しては[一応対応している](https://github.com/deepmap/oapi-codegen#additional-properties-in-type-definitions)と書いてますが、
定義が実際にどう構造体として出力されるか見てみました。



### 定義

```yml:API定義

...
components:
  schemas:
...
    Sample:
      title: Sample
      type: object
      properties:
        id:
          type: integer
          format: int64
        related_image_asset_ids:
          type: array
          items:
            type: integer
        image_asset_id_to_url_map:
          type: object
          additionalProperties:
            type: string
          description: 'example : { "1" : "https://img.com/xxxx.png" }'
      required:
        - id
        - related_image_asset_ids
        - image_asset_id_to_url_map


```

### 出力

```go

// Sample defines model for Sample.
type Sample struct {
	Id int64 `json:"id"`

	// example : { "1" : "https://img.com/xxxx.png" }
	ImageAssetIdToUrlMap Sample_ImageAssetIdToUrlMap `json:"image_asset_id_to_url_map"`
	RelatedImageAssetIds []int                       `json:"related_image_asset_ids"`
}

// example : { "1" : "https://img.com/xxxx.png" }
type Sample_ImageAssetIdToUrlMap struct {
	AdditionalProperties map[string]string `json:"-"`
}

...

// Getter for additional properties for Sample_ImageAssetIdToUrlMap. Returns the specified
// element and whether it was found
func (a Sample_ImageAssetIdToUrlMap) Get(fieldName string) (value string, found bool) {
	if a.AdditionalProperties != nil {
		value, found = a.AdditionalProperties[fieldName]
	}
	return
}

// Setter for additional properties for Sample_ImageAssetIdToUrlMap
func (a *Sample_ImageAssetIdToUrlMap) Set(fieldName string, value string) {
	if a.AdditionalProperties == nil {
		a.AdditionalProperties = make(map[string]string)
	}
	a.AdditionalProperties[fieldName] = value
}

// Override default JSON handling for Sample_ImageAssetIdToUrlMap to handle AdditionalProperties
func (a *Sample_ImageAssetIdToUrlMap) 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]string)
		for fieldName, fieldBuf := range object {
			var fieldVal string
			err := json.Unmarshal(fieldBuf, &fieldVal)
			if err != nil {
				return errors.Wrap(err, fmt.Sprintf("error unmarshaling field %s", fieldName))
			}
			a.AdditionalProperties[fieldName] = fieldVal
		}
	}
	return nil
}

// Override default JSON handling for Sample_ImageAssetIdToUrlMap to handle AdditionalProperties
func (a Sample_ImageAssetIdToUrlMap) MarshalJSON() ([]byte, error) {
	var err error
	object := make(map[string]json.RawMessage)

	for fieldName, field := range a.AdditionalProperties {
		object[fieldName], err = json.Marshal(field)
		if err != nil {
			return nil, errors.Wrap(err, fmt.Sprintf("error marshaling '%s'", fieldName))
		}
	}
	return json.Marshal(object)
}

```

```yml
additionalProperties:
  type: string
```
はセッター/ゲッター/変換レシーバ付きの専用Structとして出力されました。

構造体をvalueとしたいときは

```yml
additionalProperties:
  $ref: '#/components/schemas/Message'
```
こうしますが、こちらも同様の動作で ``` map[string]Message  ``` が出力されました。