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

Bug in merge behavior due to bug in fatih/structs #299

Open
gheinrich-dd opened this issue Jun 14, 2024 · 0 comments
Open

Bug in merge behavior due to bug in fatih/structs #299

gheinrich-dd opened this issue Jun 14, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@gheinrich-dd
Copy link

Describe the bug
Hi, recently started using your package and enjoy using it. I did unfortunately come across what seems to be a bug in fatih/structs, which ultimately ends up breaking some merge behavior for structs.Provider(). The tl;dr of the bug is that if you have a struct where all fields are default values, fatih/structs will think there was a problem representing the struct as a raw map and will leave the value in tact as the original struct value rather than turning it into map[string]any. The code that causes this can be found here.

To Reproduce

package example

import (
	"github.com/knadh/koanf"
	"github.com/knadh/koanf/providers/structs"
	"github.com/stretchr/testify/assert"
	"testing"
)

type Address struct {
	Street string `json:"street,omitempty"`
}

type Person struct {
	FirstName string   `json:"firstName,omitempty"`
	LastName  string   `json:"lastName,omitempty"`
	Address   *Address `json:"address,omitempty"`
}

func TestStructsProvider(t *testing.T) {
	expected := Person{
		FirstName: "Jane",
		LastName:  "Doe",
		Address: &Address{
			Street: "123 Street",
		},
	}

	override := Person{
		Address: &Address{
			Street: "",
		},
	}

	conf := koanf.New("::")
	err := conf.Load(structs.Provider(expected, "json"), nil)
	assert.NoError(t, err)

	err = conf.Load(structs.Provider(override, "json"), nil)
	assert.NoError(t, err)

	var actual Person
	err = conf.Unmarshal("", &actual)
	assert.NoError(t, err)

	// fails
	assert.Equal(t, expected, actual)
}

Expected behavior
In the code above, the expected behavior is that the overrides don't change anything. The street value in the Address struct is empty, and so it should get dropped out because of omitempty, effectively meaning you're merging { "address": { } } into the existing value. Instead, fatih/structs leaves the Address struct value intact rather than converting it to map[string]any and dropping out the street field, causing the street value to get trampled by the empty value.

Please provide the following information):

  • OSX
  • GoLand
  • Koanf v1.5.0

Additional context
In my company's codebase, I got around this issue by implementing a custom structs provider that does a json marshal and unmarshal into map[string]any.

@gheinrich-dd gheinrich-dd added the bug Something isn't working label Jun 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant