With jsonnet, I have multiple objects, and want to merge those into a single object. I know, that I can use the '+' operator to merge objects. But I do not know how to apply this operator to a list of objects.
Specifically, I want to provide a function, which merges an arbitrary number of objects. The objects can be provided as list items, or as dictionary fields.
My usecase is to provide application configuration, merged from a hierarchy of sources.
My current approach is:
Example: This is my initial config object, with N nested objects:
local config = {
conf1: { key1: 'val', foo: 'bar' },
confN: { keyN: 'val', foo: 'baz' }
}
I want to merge the nested N objects into a single object, result should be:
local merged_config = {
key1: 'val',
keyN: 'val',
foo: 'baz'
}
I tried to transform the initial object into a list of objects, and use a comprehension to merge the objects:
# get array of nested objects
local values = std.objectValuesAll(config),
# init merged config
local merged_config = {}
# use comprehension to merge objects
{
merged_config: merged_config + x
for x in config
}
But here I am stuck. I try to use a comprehensions as for-loop, but cannot get this to work. Probably this is the wrong approach.
Is there a better apporach then using a comprehension here? Any help is really appreciated!
The problem with comprehensions under this context is that you can't duplicate a key, i.e. below code would only work if there are no dups (foo
in your example):
{
[k]: mainVal[k]
for mainVal in std.objectValues(config)
for k in std.objectFields(mainVal)
}
BTW besides the possible solution I provide here below, keep in mind that you're relying on the sort order of the "main" object keys (fields), which is not guaranteed when visiting objects' fields (that's why there's a std.sort()
below)
The solution uses std.foldl() over the array of config fields (conf1
... confN
in your case), to aggregate their values (and ok to override them).
local config = {
conf1: { key1: 'val', foo: 'bar' },
confN: { keyN: 'val', foo: 'baz' },
};
// Loop over config's keys, aggregating their values
std.foldl(
function(agg, key) agg + config[key],
std.sort(std.objectFields(config)),
{},
)
$ jsonnet foo.jsonnet
{
"foo": "baz",
"key1": "val",
"keyN": "val"
}