Skip to content

Default decode hooks are not accessible when overriding DecodeHook #2139

Description

@andig

Preflight Checklist

  • I have searched the issue tracker for an issue that matches the one I want to file, without success.

Problem Description

WithDecodeHook (and the DecodeHook decoder option) replace viper's default hook chain rather than extend it. The default chain is built in defaultDecoderConfig:

decodeHook = mapstructure.ComposeDecodeHookFunc(
	mapstructure.StringToTimeDurationHookFunc(),
	stringToWeakSliceHookFunc(","),
)

stringToWeakSliceHookFunc is unexported, so any application that adds a single custom hook silently loses the weak string-to-slice behaviour and cannot restore it — the only workaround is to copy the function into the application.

The difference is observable: decoding "a,b" into []string yields ["a", "b"] with viper's default chain and ["a,b"] without it (with WeaklyTypedInput).

Proposed Solution

Either:

  1. Export the default chain, e.g. viper.DefaultDecodeHook() returning the composed hook (and/or export StringToWeakSliceHookFunc), so callers can compose:

    viper.WithDecodeHook(mapstructure.ComposeDecodeHookFunc(
        myHook,
        viper.DefaultDecodeHook(),
    ))
  2. Or add an option that appends to the defaults instead of replacing them, e.g. viper.WithAdditionalDecodeHook(h).

Option 1 is the smaller change and keeps composition explicit.

Alternatives Considered

Copying stringToWeakSliceHookFunc into the application — works, but duplicates viper internals and drifts when the default chain changes (the source already carries a TODO about replacing that implementation).

Additional Information

Viper v1.21.0. Encountered while adding an ${env:NAME} resolution hook to an application's config decoding, where the rest of viper's default decoding behaviour must stay intact.


🤖 Filed with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions