Accessing Nested Config with Viper
A Slice of Structs
Let’s start with the configured colours to send to my LED shelf (which I realised I didn’t blog about, but I should!) In the config.yaml
file it is a series of objects, with properties red
, green
and blue
:
shelf_lights:
- red: 120
blue: 200
- red: 120
green: 150
- blue: 200
green: 40
red: 60
In my code, I have a struct called LEDColour
to represent each of these objects, and it uses field tags to explain how the yaml data fits into the struct – similar to how the JSON field tags work if you’ve seen those. Viper uses a neat package called mapstructure to handle this part. My struct looks like this:
type LEDColour struct { Red uint8 `mapstructure:"red"` Green uint8 `mapstructure:"green"` Blue uint8 `mapstructure:"blue"` }
To wrangle the yaml data into this structure, I declare the variable it will go into, then Viper has an UnmarshalKey
which allows me to grab just the shelf_lights
section from config and work on that.
var lights []LEDColour viper.UnmarshalKey("shelf_lights", &lights)
There was a lot of preamble but the actual moment it happens is neat!
Map of Structs with String Keys
This is pretty similar to above but I think a specific example might help. With a section of the yaml config file like this:
obs_scenes:
Camera:
name: Camera
image: "/camera.png"
Offline:
name: Offline
image: "/offline.png"
Secrets:
name: Secrets
image: "/secrets.png"
I have another struct, also with mapstructure features:
type ObsScene struct { Name string `mapstructure:"name"` Image string `mapstructure:"image"` ButtonId int }
The ButtonId
field isn’t updated until the scene is assigned to a button dynamically (this is from my streamdeck utility, OBS is a video streaming tool, don’t worry if the words don’t mean anything! One OBS has many scenes) so we don’t need to include it when we’re reading from config. Which looks like this:
var buttons_obs map[string]*ObsScene buttons_obs = make(map[string]*ObsScene) viper.UnmarshalKey("obs_scenes", &buttons_obs)
As usual, Viper has us covered and while for many applications it makes sense to read in the whole config file and refer to each setting as you need it, this ability to transform sections of config is very handy indeed!
Also published on Medium.