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

Support for merging slices #269

Open
SamerJ opened this issue Jan 24, 2024 · 2 comments
Open

Support for merging slices #269

SamerJ opened this issue Jan 24, 2024 · 2 comments
Labels
question Further information is requested

Comments

@SamerJ
Copy link

SamerJ commented Jan 24, 2024

As of today, the library works in most scenarios, but it has one annoying downside; it doesn't support slices.
At least not in the way you'd expect like merging them.
The library does support adding a custom merge function, but it's not scoped and you end up writing the entire merge algorithm. Another library I came across had the ability to define merge functions for certain types. In which case, you could provide a merge function for Slices and rely on the default behavior for everything else.

Any chance this library can be improved by adding scoped merge functions? Are there any workarounds that can be employed to end up merging slices?

@knadh
Copy link
Owner

knadh commented Jan 24, 2024

Can you give an example with some pseudocode illustrating what you're referring to?

@knadh knadh added the question Further information is requested label Jan 24, 2024
@SamerJ
Copy link
Author

SamerJ commented Jan 24, 2024

@knadh

Take this struct for example:

type Parent struct {
	Name  string `koanf:"name"`
	Child Child  `koanf:"child"`
}

type Child struct {
	Item1 map[string][]string `koanf:"item1"`
}

Assume you have 2 "Parent" structs you would like to merge.

	parent1 := Parent{
		Name: "name",
		Child: Child{
			Item1: map[string][]string{
				"Key1": {"value1", "value2"},
			},
		},
	}

	parent2 := Parent{
		Name: "new name",
		Child: Child{
			Item1: map[string][]string{
				"Key1": {"value3"},
				"Key2": {"value1"},
			},
		},
	}

Intended result:

	mergedParent := Parent{
		Name: "new name",
		Child: Child{
			Item1: map[string][]string{
				"Key1": {"value1", "value2", "value3"},
				"Key2": {"value1"},
			},
		},
	}

However, as is known, koanf will simply replace slice values rather than append them.
Actual result:

	actualMergedParent := Parent{
		Name: "new name",
		Child: Child{
			Item1: map[string][]string{
				"Key1": {"value3"},
				"Key2": {"value1"},
			},
		},
	}

The suggestion/request is to have something like

k.Load(structs.Provider(config, "koanf"), nil, koanf.WithMergeFuncForType(reflect.Slice, mergeFunc)) 

As a result, you would only need to write the code to handle slices and rely on the default merging algorithm for anything else. WDYT?

Inspired from another library I had seen:
https://github.com/InVisionApp/conjungo

	opts := conjungo.NewOptions()
	opts.SetKindMergeFunc(reflect.Slice, func(target, source reflect.Value, o *conjungo.Options) (reflect.Value, error) {
		//...
		return target, nil
	})
	err = conjungo.Merge(dest, src, opts)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants