Skip to content

feature: Add map field name to convert structs dynamically instead of individually with a tag.#149

Merged
sagikazarmark merged 3 commits intogo-viper:mainfrom
thespags:main
Jan 12, 2026
Merged

feature: Add map field name to convert structs dynamically instead of individually with a tag.#149
sagikazarmark merged 3 commits intogo-viper:mainfrom
thespags:main

Conversation

@thespags
Copy link
Copy Markdown

Feature to solve #40

MapFieldName = func(s string) {
  return strings.ToLower(s)
}

or #148

MapFieldName = func(s string) {
  return strcase.ToLowerSnakeCase(s)
}

@thespags
Copy link
Copy Markdown
Author

Hi @sagikazarmark , I'm curious about your thoughts on adding this dynamic matching for decodemapfromstruct,
This ends up helping Viper, so I can bind my config value against environment variables FOO_BAR, for an identifier FooBar, without having to write a mapstructure tag for every identifier.

@sagikazarmark
Copy link
Copy Markdown
Member

If I understand correctly, you want to avoid tagging your struct with mapstructure struct tags, correct?

This certainly seems like an easy fix, although there are a couple caveats:

  • if IgnoreUntaggedFields is set to true, the field will still be omitted (which I guess could be unexpected to some, since not using tags is the whole point of this feature, still, the current behavior is the right one I believe, especially if you want to mix using tags and the mapper)
  • There is an "opposite" direction mapping as well that's supposed to work: from maps to structs. I'm not sure from the top of my head how that would work in this case (but Viper actually does that). So at least a test would be necessary.

Need to think through a couple other edge cases before this can land.

@thespags
Copy link
Copy Markdown
Author

If I understand correctly, you want to avoid tagging your struct with mapstructure struct tags, correct?

Yes the challenge I was having nested into #148 comment:

Specifically, I'm trying to have viper map something like FooBar to be loaded from an environmental variable FOO_BAR without having to create mapstructure for each key. I can't use SetEnvKeyReplacer because by that time the casing has been lost, so I would get FOOBAR.

@thespags
Copy link
Copy Markdown
Author

if IgnoreUntaggedFields is set to true, the field will still be omitted (which I guess could be unexpected to some, since not using tags is the whole point of this feature, still, the current behavior is the right one I believe, especially if you want to mix using tags and the mapper)

Yeah, if you use IgnoreUntaggedFields then it would negate the point of this mapping.

There is an "opposite" direction mapping as well that's supposed to work: from maps to structs. I'm not sure from the top of my head how that would work in this case (but Viper actually does that). So at least a test would be necessary.

I added a test case to demonstrate this, I believe this behavior makes sense. If you specify a tag, we use that, otherwise we will convert the struct's field name for the map.

@thespags
Copy link
Copy Markdown
Author

@sagikazarmark I was wondering if you had a chance to follow up on my updates. Thank you.

Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
Copy link
Copy Markdown
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @thespags

@sagikazarmark sagikazarmark merged commit 6471aa6 into go-viper:main Jan 12, 2026
11 checks passed
radermacher-iits pushed a commit to kubara-io/kubara that referenced this pull request Feb 19, 2026
…5.0 (#232)

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) | require | minor | `v2.4.0` → `v2.5.0` |

---

### Release Notes

<details>
<summary>go-viper/mapstructure (github.com/go-viper/mapstructure/v2)</summary>

### [`v2.5.0`](https://github.com/go-viper/mapstructure/releases/tag/v2.5.0)

[Compare Source](go-viper/mapstructure@v2.4.0...v2.5.0)

#### What's Changed

- Print qualified type name when ErrorUnused=true causes errors for unused keys in embedded fields by [@&#8203;jmacd](https://github.com/jmacd) in [#&#8203;113](go-viper/mapstructure#113)
- build(deps): bump github/codeql-action from 3.29.2 to 3.29.5 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;126](go-viper/mapstructure#126)
- build(deps): bump github/codeql-action from 3.29.7 to 3.29.10 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;131](go-viper/mapstructure#131)
- build(deps): bump actions/checkout from 4.2.2 to 5.0.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;129](go-viper/mapstructure#129)
- feat: support for automatically initializing squashed pointer structs by [@&#8203;tuunit](https://github.com/tuunit) in [#&#8203;71](go-viper/mapstructure#71)
- build(deps): bump actions/setup-go from 5.5.0 to 6.0.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;134](go-viper/mapstructure#134)
- build(deps): bump ossf/scorecard-action from 2.4.2 to 2.4.3 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;142](go-viper/mapstructure#142)
- Fix slice deep map (owned) by [@&#8203;jphastings](https://github.com/jphastings) in [#&#8203;144](go-viper/mapstructure#144)
- chore: fix lint violations by [@&#8203;sagikazarmark](https://github.com/sagikazarmark) in [#&#8203;157](go-viper/mapstructure#157)
- chore: switch to devenv by [@&#8203;sagikazarmark](https://github.com/sagikazarmark) in [#&#8203;158](go-viper/mapstructure#158)
- build(deps): bump actions/upload-artifact from 4.6.2 to 5.0.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;151](go-viper/mapstructure#151)
- build(deps): bump github/codeql-action from 3.29.10 to 4.31.2 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;153](go-viper/mapstructure#153)
- build(deps): bump golangci/golangci-lint-action from 8.0.0 to 9.0.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;154](go-viper/mapstructure#154)
- build(deps): bump actions/checkout from 5.0.0 to 6.0.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;160](go-viper/mapstructure#160)
- build(deps): bump actions/setup-go from 6.0.0 to 6.1.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;159](go-viper/mapstructure#159)
- build(deps): bump github/codeql-action from 4.31.7 to 4.31.8 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;162](go-viper/mapstructure#162)
- build(deps): bump actions/upload-artifact from 5.0.0 to 6.0.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;161](go-viper/mapstructure#161)
- build(deps): bump github/codeql-action from 4.31.8 to 4.31.9 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;163](go-viper/mapstructure#163)
- feature: Add map field name to convert structs dynamically instead of individually with a tag. by [@&#8203;thespags](https://github.com/thespags) in [#&#8203;149](go-viper/mapstructure#149)
- feat(decoder): support multiple tag names in order by [@&#8203;DarkiT](https://github.com/DarkiT) in [#&#8203;59](go-viper/mapstructure#59)
- feat: optional root object name by [@&#8203;andreev-fn](https://github.com/andreev-fn) in [#&#8203;137](go-viper/mapstructure#137)
- Add unmarshaler interface by [@&#8203;sagikazarmark](https://github.com/sagikazarmark) in [#&#8203;166](go-viper/mapstructure#166)

#### New Contributors

- [@&#8203;jmacd](https://github.com/jmacd) made their first contribution in [#&#8203;113](go-viper/mapstructure#113)
- [@&#8203;tuunit](https://github.com/tuunit) made their first contribution in [#&#8203;71](go-viper/mapstructure#71)
- [@&#8203;jphastings](https://github.com/jphastings) made their first contribution in [#&#8203;144](go-viper/mapstructure#144)
- [@&#8203;thespags](https://github.com/thespags) made their first contribution in [#&#8203;149](go-viper/mapstructure#149)
- [@&#8203;DarkiT](https://github.com/DarkiT) made their first contribution in [#&#8203;59](go-viper/mapstructure#59)
- [@&#8203;andreev-fn](https://github.com/andreev-fn) made their first contribution in [#&#8203;137](go-viper/mapstructure#137)

**Full Changelog**: <go-viper/mapstructure@v2.4.0...v2.5.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi44MC4xIiwidXBkYXRlZEluVmVyIjoiNDIuODAuMSIsInRhcmdldEJyYW5jaCI6Im1hc3RlciIsImxhYmVscyI6W119-->

Reviewed-on: https://kubara.git.onstackit.cloud/STACKIT/kubara/pulls/232
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.

2 participants