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] Slice encoding drops empty values rather than encoding them as nil or default #215

Open
tombuente opened this issue Apr 13, 2024 · 3 comments
Labels

Comments

@tombuente
Copy link

tombuente commented Apr 13, 2024

Current Behavior

r.ParseForm()
fmt.Println(r.PostForm["id"], len(r.PostForm["id"])) // [1  15] 3

var decoder = schema.NewDecoder()
var i Document
// r.PostForm is a map of our POST form values
err = decoder.Decode(&i, r.PostForm)
if err != nil {
    fmt.Println(err)
}

fmt.Println(i.ID, "Length", len(i.ID)) // ID [1 15] Length 2

When called with id=1, id=, id=15

The behavior is rather unfortunate when decoding values that matter when equal to "".
For example, when two slices are related to each other.

type Document struct {
	RowID   []int64  `schema:"row_id"`
	RowName []string `schema:"row_name"`
}

Now RowID[0]and RowName[0] build a pair. But since gorilla/schema drops empty strings for some reason rather than settings it to Go's default for that value or using the default value defined by tags, the relationship breaks.

Expected Behavior

fmt.Println(i.ID, "Length", len(i.ID)) // ID [1 15] Length 3, add "" to struct slice
fmt.Println(i.ID, "Length", len(i.ID)) // ID [&addr nil &addr] Length 3, add nil to struct slice when field is pointer
@tombuente tombuente added the bug label Apr 13, 2024
@lll-lll-lll-lll
Copy link
Contributor

@tombuente
By passing true to the decoder's ZeroEmpty method, zero values for the field's type will be set.

schema/decoder.go

Lines 38 to 48 in cd59f2f

// ZeroEmpty controls the behaviour when the decoder encounters empty values
// in a map.
// If z is true and a key in the map has the empty string as a value
// then the corresponding struct field is set to the zero value.
// If z is false then empty strings are ignored.
//
// The default value is false, that is empty values do not change
// the value of the struct field.
func (d *Decoder) ZeroEmpty(z bool) {
d.zeroEmpty = z
}

@lll-lll-lll-lll
Copy link
Contributor

r.ParseForm()
fmt.Println(r.PostForm["id"], len(r.PostForm["id"])) // [1  15] 3

var decoder = schema.NewDecoder()
// fix
decoder.ZeroEmpty(true)
var i Document
// r.PostForm is a map of our POST form values
err = decoder.Decode(&i, r.PostForm)
if err != nil {
    fmt.Println(err)
}

fmt.Println(i.ID, "Length", len(i.ID)) // ID [1 15] Length 2

@lll-lll-lll-lll
Copy link
Contributor

@tombuente
The specific processing is as follows.

schema/decoder.go

Lines 355 to 358 in cd59f2f

if value == "" {
if d.zeroEmpty {
items = append(items, reflect.Zero(elemT))
}

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

No branches or pull requests

2 participants