Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions formam.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ type DecoderOptions struct {
// Prefer UnmarshalText over custom types.
PrefUnmarshalText bool

// Disable UnmarshalText interface
DisableUnmarshalText bool

// Ignore unknown form fields. By default unknown fields are an error
// (although all valid keys will still be decoded).
IgnoreUnknownKeys bool
Expand Down Expand Up @@ -371,20 +374,27 @@ func (dec *Decoder) traverseInMap(byField bool) {

// decode sets the value in the field
func (dec *Decoder) decode() error {
// check if has UnmarshalText method or a custom function to decode it
if dec.opts.PrefUnmarshalText {
if ok, err := dec.isUnmarshalText(dec.curr); ok || err != nil {
return err
}
// if DisableUnmarshalText is true then only use customType if available
if dec.opts.DisableUnmarshalText {
if ok, err := dec.isCustomType(); ok || err != nil {
return err
}
} else {
if ok, err := dec.isCustomType(); ok || err != nil {
return err
}
if ok, err := dec.isUnmarshalText(dec.curr); ok || err != nil {
return err
// check if has UnmarshalText method or a custom function to decode it
if dec.opts.PrefUnmarshalText {
if ok, err := dec.isUnmarshalText(dec.curr); ok || err != nil {
return err
}
if ok, err := dec.isCustomType(); ok || err != nil {
return err
}
} else {
if ok, err := dec.isCustomType(); ok || err != nil {
return err
}
if ok, err := dec.isUnmarshalText(dec.curr); ok || err != nil {
return err
}
}
}

Expand Down Expand Up @@ -654,6 +664,8 @@ var (

// isUnmarshalText returns a boolean and error. The boolean is true if the
// field's type implements TextUnmarshaler, and false if not.
// If the field implements TextUnmarshaler, then it is used to decode the value
// in the field.
func (dec *Decoder) isUnmarshalText(v reflect.Value) (bool, error) {
// check if implements the interface
m, ok := v.Interface().(encoding.TextUnmarshaler)
Expand Down
41 changes: 41 additions & 0 deletions formam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,47 @@ func TestArrayLength(t *testing.T) {
}
}

type StringWithUnmarshalText string

func (s *StringWithUnmarshalText) UnmarshalText(data []byte) error {
*s = "string by UnmarshalText"
return nil
}

func TestEnableUnmarshalText(t *testing.T) {
s := struct {
Text StringWithUnmarshalText
}{}
vals := url.Values{
"Text": []string{"string by form"},
}
dec := formam.NewDecoder(&formam.DecoderOptions{})
if err := dec.Decode(vals, &s); err != nil {
t.Fatalf("error when decode %s", err)
}
if s.Text != "string by UnmarshalText" {
t.Errorf("the UnmarshalText hasn't been called")
}
}

func TestDisableUnmarshalText(t *testing.T) {
s := struct {
Text StringWithUnmarshalText
}{}
vals := url.Values{
"Text": []string{"string by form"},
}
dec := formam.NewDecoder(&formam.DecoderOptions{
DisableUnmarshalText: true,
})
if err := dec.Decode(vals, &s); err != nil {
t.Fatalf("error when decode %s", err)
}
if s.Text != "string by form" {
t.Errorf("the UnmarshalText has been called")
}
}

// errorContains checks if the error message in out contains the text in
// want.
//
Expand Down