Describe map-of-slice values via additionalProperties#108
Merged
Conversation
Coverage Report for CI Build 24847921383Coverage decreased (-0.1%) to 52.863%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
cesartw
reviewed
Apr 23, 2026
| PrimSlices map[string][]string `json:"primSlices"` // Map of primitive slices. | ||
| StructSlice map[int64][]aStruct `json:"structSlice"` // Map of local struct slices. | ||
| OtherSlice map[string][]otherpkg.OtherStruct `json:"otherSlice"` // Map of cross-package struct slices. | ||
| } |
Contributor
There was a problem hiding this comment.
the same happens for a map of maps but honestly I don't know if it should be addressed.
maps are too opened for web apis and feel lazy
Suggested change
| } | |
| OtherMap map[string]map[string]otherpkg.OtherStruct `json:"otherMap"` // Other map comment. | |
| } |
Contributor
Author
There was a problem hiding this comment.
I've added nested map support there, although you'd be best positioned to know how it might impact performance .
cesartw
approved these changes
Apr 23, 2026
rafaeljusto
approved these changes
Apr 23, 2026
The `*ast.MapType` handler only resolved map values of kind `*ast.Ident`/`*ast.SelectorExpr`, so fields typed as `map[K][]T` silently dropped the element type and rendered as `type: object` with no `additionalProperties`. Consumers (openapi-typescript, etc.) then saw an opaque `Record<string, never>` where the server actually emits a map of arrays. Detect a slice value up front and build an array schema for it via `resolveArray`, attaching it as `additionalProperties`. While here, make `prefixPropertyReferences` recurse into nested `additionalProperties` and `items` so references inside the new array schema get the `#/definitions/...` prefix they need. Fixture `struct-map` grows three new cases covering primitive, local, and cross-package slice element types.
Keeps fieldToSchema's cyclomatic complexity under the gocyclo threshold (65). Pure refactor — no behavior change, no new tests needed.
A `map[K]map[K2]V` field previously dropped the inner map's value type: `findTypeIdent` only handles `Ident`/`SelectorExpr`, so a map-typed value fell through to the open-object fallback. Detect `*ast.MapType` up front and recurse, producing nested `additionalProperties`. `prefixSchemaReferences` already walks `AdditionalProperties`, so `$ref`s inside the nested schema are rewritten correctly without further changes.
`resolveMap` compared the raw Go type name against the JSON-schema primitive set, so `int`/`bool`/`float64` failed the check and fell through to an open-object fallback. Run `JSONSchemaType` first so `int`→`integer`, `bool`→`boolean`, etc. match.
bda12c4 to
4c622b1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Fixes a gap in
*ast.MapTypehandling. Fields typed asmap[K][]Tpreviously dropped the element type — they rendered astype: objectwith noadditionalProperties, which downstream tools (openapi-typescript, etc.) flatten toRecord<string, never>.The value-type resolver (
findTypeIdent) only handlesIdent/SelectorExpr, so a slice value fell through the error branch. This PR detects*ast.ArrayTypevalues up front and builds an array schema via the existingresolveArray, then attaches it asadditionalProperties.While here,
prefixPropertyReferencesnow recurses into nesteditemsandadditionalProperties, so$refvalues inside the new array schema get the#/definitions/...prefix.Before / after
Given
map[int64][]SomeStruct:Before
After
Tests
Extended the existing
struct-mapfixture with three new fields covering primitive, local-struct, and cross-package-struct slice element types. All existing tests still pass.Why
map[K][]Tis a natural Go shape for "group these items by X" response payloads. Without this fix, any such field ends up as an opaque object in the spec and consumers lose all type information about the slice elements. Fixing it here avoids per-field workarounds in downstream type generators.