spf13 / viper

Go configuration with fangs
MIT License
26.95k stars 2.01k forks source link

Unmarshal function cannot parse string map stored in environment #1671

Open nouzun opened 11 months ago

nouzun commented 11 months ago

Preflight Checklist

Viper Version

1.17.0

Go Version

1.21

Config Source

Environment variables

Format

YAML

Repl.it link

https://replit.com/@nouzun/viperenvunmarshal?v=1#main.go

Code reproducing the issue

package main

import (
  "fmt"
  "strings"
  "os"

  "github.com/spf13/pflag"
  "github.com/spf13/viper"
)

type Conf struct {
  StringMapItem map[string]string `mapstructure:"string-map-item"`
}

func main() {

  viper.Reset()
  viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))

  testFlags := &pflag.FlagSet{}
  testFlags.StringToString("string-map-item", nil, "")

  if err := viper.BindEnv("string-map-item", "STRING_MAP_ITEM"); err != nil {
    return
  }

  os.Setenv("STRING_MAP_ITEM", "x=foo,y=boo")

  cfg := &Conf{}
  err := viper.Unmarshal(cfg)
  if err != nil {
    fmt.Println(err)
  }
  fmt.Println(cfg)
}

Expected Behavior

I'd expect viper.Unmarshal to parse "x=foo,y=boo" string into the variable map[string]string

Actual Behavior

viper.Unmarshal returns the following error

'string-map-item' expected a map, got 'string'

Steps To Reproduce

No response

Additional Information

No response

github-actions[bot] commented 11 months ago

👋 Thanks for reporting!

A maintainer will take a look at your issue shortly. 👀

In the meantime: We are working on Viper v2 and we would love to hear your thoughts about what you like or don't like about Viper, so we can improve or fix those issues.

⏰ If you have a couple minutes, please take some time and share your thoughts: https://forms.gle/R6faU74qPRPAzchZ9

📣 If you've already given us your feedback, you can still help by spreading the news, either by sharing the above link or telling people about this on Twitter:

https://twitter.com/sagikazarmark/status/1306904078967074816

Thank you! ❤️

osjason commented 11 months ago

It just can be convert to map[string]interface{}, WTF?

retr0h commented 10 months ago

@nouzun did you come up with a workaround?

sagikazarmark commented 10 months ago

Unmarshal works a bit differently from Get functions. It uses mapstructure under the hood.

You can write your own decode hook based on this post: https://sagikazarmark.hu/blog/decoding-custom-formats-with-viper/