Skip to content

Surgical update using a deep string path to the value #1140

@ghstahl

Description

@ghstahl

Given a fully merged config, I would like to update an item based upon a path to the item.

Assume the following JSON config.

{
	"id": "0001",
	"type": "donut",
	"name": "Cake",
	"ppu": 0.55,
	"batters": {
		"batter": [{
				"type": "Regular"
			},
			{
				"type": "Chocolate"
			},
			{
				"type": "Blueberry"
			},
			{
				"type": "Devil's Food"
			}
		],
		"topping": [
			"Icing", "Chocolate"
		]
	}
}
v := New()
v.SetConfigType("json")
v.ReadConfig(bytes.NewBuffer(jsonExample))

os.Setenv("batters.doesnotexist", "ted")
os.Setenv("batters.batter.0.type", "bob")
os.Setenv("batters.topping.1", "frosting")
v.SurgicalPathUpdateFromEnv()

os.Remove("batters.doesnotexist")
os.Remove("batters.batter.0.type")
os.Remove("batters.topping.1")

should result in the following updates;

{
	"id": "0001",
	"type": "donut",
	"name": "Cake",
	"ppu": 0.55,
	"batters": {
		"batter": [{
				"type": "bob"
			},
			{
				"type": "Chocolate"
			},
			{
				"type": "Blueberry"
			},
			{
				"type": "Devil's Food"
			}
		],
		"topping": [
			"Icing", "frosting"
		]
	}
}

Describe alternatives you've considered
reference project - viperEx
I was able to do this after the fact with the following technique

	allSettings := myViper.AllSettings()

        myViperEx := New("__")
	myViperEx.SurgicalUpdate("nest__Eggs__0__Weight", 1234, allSettings)
	myViperEx.SurgicalUpdate("nest__Eggs__0__SomeValues__1__Value", "abcd", allSettings)
	myViperEx.SurgicalUpdate("nest__Eggs__0__SomeStrings__1__", "abcd", allSettings)
	myViperEx.SurgicalUpdate("junk__A", "abcd", allSettings)
	myViperEx.SurgicalUpdate("nest__junk", "abcd", allSettings)

        settings := Settings{}
	err = myViper.Unmarshal(&settings)

where I wrote a ViperEx helper that updated the AllSettings that viper owns. Arguably it is really more of a mapstructure thing that traverses maps, etc. The difference is really should this be a separate project vs being part of Viper.

This type of processing is part of the asp.net core configuration builder which is very similar in design to the viper design.
So, I vote for being part of Viper.

On the viper side, the biggest issue I think is setting an item in an array. i.e.

viper.Set("a.b.1.name", "bob")

This doesn't exist, but it should, especially when there is a getter that allows it.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions