Skip to content

feat: promote embedded (anonymous) structs across loaders#48

Open
rlball wants to merge 1 commit into
mainfrom
rball-cursor/promote-embedded-structs
Open

feat: promote embedded (anonymous) structs across loaders#48
rlball wants to merge 1 commit into
mainfrom
rball-cursor/promote-embedded-structs

Conversation

@rlball

@rlball rlball commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes embedded (anonymous) struct fields behave consistently across all loaders by promoting/flattening them, the same mental model as Go's encoding/json.

Previously the behavior was inconsistent for the same embedded field:

Loader Before After
env EMBEDDED_DB_HOST (type-name prefix) HOST (promoted)
flag --embedded-db-host (type-name prefix) --host (promoted)
json top-level Host (already flat) unchanged
toml top-level Host (already flat) unchanged
yaml nested under embeddeddb: top-level host with yaml:",inline"

Changes

  • util/node: add IsAnonymous() helper.
  • load/env, load/flag, render: drop the type-name prefix for embedded struct fields. Guarded to structs only (excludes time.Time and embedded basic types). An explicit env/flag tag still overrides.
  • Docs: full struct-tag reference (every tag + accepted values + example) and a new "Embedded (anonymous) structs" section covering the yaml:",inline" and exported-type requirements.

Behavior change / compatibility

Anyone who relied on the previously-undocumented env/flag prefix for an embedded struct (e.g. EMBEDDED_DB_HOST) must switch to the promoted name (HOST) or convert the embed to a named field. Named struct fields are unaffected.

Notes surfaced during verification (documented in README)

  • gopkg.in/yaml.v2 does not inline anonymous structs automatically; yaml:",inline" is required.
  • Embedded types must be exported, or env/flag loaders skip them (unexported fields aren't settable via reflection).

Test plan

  • TestEmbeddedStructPromotionEnv — env promotes HOST/PORT (no prefix).
  • TestEmbeddedStructPromotionFiles — yaml (inline)/toml/json all flatten.
  • Existing suite (incl. named-struct/omitprefix tests) still passes.
  • go test -race ./..., go vet ./..., gofmt -l . all clean.

Embedded struct fields are now flattened/promoted consistently instead
of being prefixed with the embedded type name. The env and flag loaders
previously prefixed embedded fields (EMBEDDED_DB_HOST), while json/toml
flattened them, leaving behavior inconsistent across formats.

The env, flag, and render name generators now drop the type-name prefix
for embedded struct fields (guarded to structs only, excluding time.Time
and embedded basic types), matching json/toml and Go's encoding/json
promotion. yaml requires a yaml:",inline" tag (yaml.v2 limitation).

Also document every supported struct field tag with its accepted values
and examples, and add an embedded-struct section to the README.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant