gorilla / schema

Package gorilla/schema fills a struct with form values.
https://gorilla.github.io
BSD 3-Clause "New" or "Revised" License
1.38k stars 227 forks source link

[Question] Form encoding/decoding ignores slice of struct #214

Open tommysalt opened 6 months ago

tommysalt commented 6 months ago

Current Behavior

When encoding/decoding from data with slices of custom structs, they are ignored even thought the examples mention:

[...] struct [...] a slice or a pointer to a slice of one of the above types

Output:

map[name:[Name]]

Expected Behavior

Output:

map[name:[Name], id:[1 2], amount:[1 2]

Steps To Reproduce

var encoder = schema.NewEncoder()

type Position struct {
    ID     int64 `schema:"id"`
    Amount int64 `schema:"amount"`
}

type Document struct {
    Name      string     `schema:"name"`
    Positions []Position `schema:"position"`
}

func main() {
    person := Document{"Name", []Position{{1, 1}, {2, 2}}}
    form := url.Values{}

    encoder.Encode(person, form)

    fmt.Println(form)
}

Output:

map[name:[Name]]
tommysalt commented 6 months ago

I added an if to catch the error and it seems it's missing an encoder.

    err := encoder.Encode(person, form)
    if err != nil {
        fmt.Println(err)
    }
schema: encoder not found for [{1 1} {2 2}]
tommysalt commented 6 months ago

So it seems that it's not a bug but I find the behavior rather odd because if I follow the docs they mention

[...] struct [...] a slice or a pointer to a slice of one of the above types

So why do I need a custom encoder/decoder even tho my struct only contains supported fields (int64)?

jaitaiwan commented 4 months ago

That's a great question @tommysalt thanks for bringing this to our attention. I'm not sure what the answer is right now but I'll try to answer it in the near future.

apoorvajagtap commented 1 month ago

Hello @tommysalt Thanks for bringing this up! I tried to dig a little into the encoder & this is more likely a documentation bug.

As soon as the encoder detects that the field type is a slice, it checks for the dataType, and if the dataType is custom, it returns nil as encodingfunc. So, it seems that when the documentation mentions:

a slice or a pointer to a slice of one of the above types

It actually means,

  • a slice or a pointer to a slice of one of the:
    • bool
      • float variants (float32, float64)
      • int variants (int, int8, int16, int32, int64)
      • string
      • uint variants (uint, uint8, uint16, uint32, uint64)

& probably not a struct.