-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error Unmarshal
map when key contains dot
#324
Comments
This still seems to be an issue for me. This test fails depending on v1.3.1: package main
import (
"strings"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestConfigMarshalling(t *testing.T) {
data := `
root:
ele.one: value
eletwo: value`
reader := strings.NewReader(data)
viper.SetConfigType("yaml")
err := viper.ReadConfig(reader)
require.NoError(t, err)
// Test if the fields are even correct
expected := map[string]interface{}{"ele.one": "value", "eletwo": "value"}
assert.Equal(t, expected, viper.Get("root"))
var s struct {
Root map[string]string
}
err = viper.UnmarshalKey("root", &s)
require.NoError(t, err)
} Changing the dot to, say, an underscore fixes the issue. |
Also hit this. Seems like if there's a key like "word.other" containing a dot as a map[string]interface{} key, the output turns it into a struct like:
and not
Is that expected? Anyone have pointers to override this to get the former behavior? |
Looks like // main.go
func main() {
configString := `
test:
a: 1
b: 2
c.d: 3
`
viper.SetConfigType("yaml")
err := viper.ReadConfig(bytes.NewBufferString(configString))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(viper.AllKeys())
}
As noted, the problem comes from keys with dots in as the unmarshalling uses the keys returned by I added the following functions to // viper.go
func SetKeyDelim(delim string) { v.keyDelim = delim }
func (v *Viper) SetKeyDelim(delim string) { v.keyDelim = delim } // main.go
func main() {
configString := `
test:
a: 1
b: 2
c.d: 3
`
viper.SetKeyDelim("\\")
viper.SetConfigType("yaml")
err := viper.ReadConfig(bytes.NewBufferString(configString))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(viper.AllKeys())
}
|
hopefully it will get merged soon! |
I will also say that despite it's simplicity, I imagine adding to the API is not going to be as favourable as fixing the implementation of |
I wonder, if we use dots in a key and AutomaticEnv, how will the env variable names look like? |
I'll have to look into exactly what |
Yes. Also #678 |
Waiting for spf13#673 to be merged
@sagikazarmark is it worth opening this again? |
I guess it does, since #673 was reverted. |
Hey guys, I'm hitting this problem too. Need to get a map with the key being IPs, but it fails. I've been using this library for quite a long time now for pretty much all my personal and work projects. Any chance we can get some brainstorming on this? |
You could stick your viper module to commit 99520c8 this commit was reverted but you don't need to run on latest :) |
@mschneider82 thank you for the tip! |
The alternative is to change the key delimiter which will be added in #794, this is on a branch of this repo and I assume will be merged at some point so could also lock the go module to that reference. As for a more robust solution I've been thinking about a way forward. As discussed in #766, the problem is being unable to determine from a single string, whether a given character should be part of the key name or is treated as the delimiter, eg: I believe the only way to also solve the problem for environment variable and pflag bindings is to provide viper with some sort of schema (like we do for unmarshalling), so that it knows explicitly what to do with a parameter address that might contain delimiters within key names, rather than assuming they're all separate keys. I'm not yet sure if this is something that could be achieved within v1, perhaps providing a schema would be like the feature toggle @sagikazarmark mentions in #794 (comment). |
Right, I fully intend to merge #794 soon, but I'm playing with replacing the setter with a constructor/factory function argument. I don't really like setters, and in this case it could actually mess up the internal state of Viper, so that's what blocks the PR from getting merged. |
Any workarounds in the meantime? |
I am having issues while creating TOML file. It add additional double quotes as below: |
waiting to get this bug fixed: spf13/viper#324
I have a very similar problem but with keys with |
Test code:
Output:
As you can see, when the map key contains dot,
UnmarshalKey
works correctly butUnmarshal
doesn't.The text was updated successfully, but these errors were encountered: