Skip to content
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

Unmarshal doesn't work for json keys with _ #498

Closed
kubaugustyn opened this issue May 15, 2018 · 5 comments
Closed

Unmarshal doesn't work for json keys with _ #498

kubaugustyn opened this issue May 15, 2018 · 5 comments

Comments

@kubaugustyn
Copy link

Hi, so it seems that Unmarshal won't work with JSON keys, that have underscores. Here's some code:

package main

import (
	"bytes"
	"fmt"

	"github.com/spf13/viper"
)

type ConfigUnderscores struct {
	FooBar string `json:"foo_bar"`
}

type Config struct {
	FooBar string `json:"fooBar"`
}

var content1 = []byte(`
{
	"foo_bar": "foo"
}`)

var content2 = []byte(`
{
	"fooBar": "foo"
}`)

func main() {
	var c1 ConfigUnderscores
	var c2 Config

	viper.SetConfigType("json")
	viper.ReadConfig(bytes.NewReader(content1))

	viper.Unmarshal(&c1)
	fmt.Printf("ConfigUnderscores: %v\n", c1)

	viper.ReadConfig(bytes.NewReader(content2))
	viper.Unmarshal(&c2)
	fmt.Printf("Config: %v\n", c2)
}

Output:

ConfigUnderscores: {}
Config: {foo}
@cbroglie
Copy link

Try using mapstructure instead of json in the struct tags

@kubaugustyn
Copy link
Author

Actually works! Thanks!

@vanugrah
Copy link

vanugrah commented Aug 5, 2018

A quick not here about the use of json vs mapstructure. While you can create a struct with json tags like this:

type Config struct {
    FormalChicken string `json: "formal_chicken"`
    WaterPankcake string `json: "water_pancake"`
    TreeFloof     string `json: "tree_floof"`
    DangerNoodle  string `json: "danger_noodle"`
}

Doing the same with mapstructure will result in an empty config:

type Config struct {
    FormalChicken string `mapstructure: "formal_chicken"`
    WaterPankcake string `mapstructure: "water_pancake"`
    TreeFloof     string `mapstructure: "tree_floof"`
    DangerNoodle  string `mapstructure: "danger_noodle"`
}

For this to work there cannot be any spaces between the tag and the key name. For example:

type Config struct {
    FormalChicken string `mapstructure:"formal_chicken"`
    WaterPankcake string `mapstructure:"water_pancake"`
    TreeFloof     string `mapstructure:"tree_floof"`
    DangerNoodle  string `mapstructure:"danger_noodle"`
}

I wish not to disclose the amount of time I spent on that haha

@pindamonhangaba
Copy link

You can also change the tag used in mapstructure:

type ConfigUnderscores struct {
	FooBar string `json:"foo_bar"`
}
config := ConfigUnderscores{}
err := v.Unmarshal(*config , func(c *mapstructure.DecoderConfig) {
    c.TagName = "json"
})

@sagikazarmark
Copy link
Collaborator

This is already covered in the troubleshooting guide: https://github.com/spf13/viper/blob/master/TROUBLESHOOTING.md#unmarshaling-doesnt-work

nobe4 added a commit to nobe4/gh-not that referenced this issue Jun 23, 2024
Some keys didn't unmarshal correctly, this was due to a lack of
understanding of how mapstructure works. Leaving `yaml:...` is incorrect
and should be replaced by `mapstructure:...` instead.

It's a bit confusing, but fixes the configuration unmarshal'ing now.

See
- https://github.com/spf13/viper/blob/master/TROUBLESHOOTING.md#unmarshaling-doesnt-work
- spf13/viper#498 (comment)
- spf13/viper#498 (comment)
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

No branches or pull requests

5 participants