Viper: Unmarshal doesn't work for json keys with `_`

Created on 15 May 2018  路  3Comments  路  Source: spf13/viper

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}

Most helpful comment

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

All 3 comments

Try using mapstructure instead of json in the struct tags

Actually works! Thanks!

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

Was this page helpful?
0 / 5 - 0 ratings