From d0e4c24cff97ae983e9847e0ed5a02dc10013d41 Mon Sep 17 00:00:00 2001 From: Emil Davtyan Date: Wed, 21 Mar 2018 17:33:53 +0100 Subject: [PATCH] Fix handling of empty value. (#104) If a value is decoding into a type that implements the encoding.TextUnmarshaler interface, the decoder should use it's UnmarshalText method in all instances including an empty value. Previously, would ignore the method decoding the field as the empty value of the type. --- decoder.go | 10 +++++----- decoder_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/decoder.go b/decoder.go index 16ece12..5352a90 100644 --- a/decoder.go +++ b/decoder.go @@ -283,11 +283,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values val = values[len(values)-1] } - if val == "" { - if d.zeroEmpty { - v.Set(reflect.Zero(t)) - } - } else if conv != nil { + if conv != nil { if value := conv(val); value.IsValid() { v.Set(value.Convert(t)) } else { @@ -321,6 +317,10 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values } } } + } else if val == "" { + if d.zeroEmpty { + v.Set(reflect.Zero(t)) + } } else if conv := builtinConverters[t.Kind()]; conv != nil { if value := conv(val); value.IsValid() { v.Set(value.Convert(t)) diff --git a/decoder_test.go b/decoder_test.go index ac4898a..ee839e9 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -1737,3 +1737,33 @@ func TestTextUnmarshalerTypeSliceOfStructs(t *testing.T) { t.Fatal("Expecting invalid path error", err) } } + +type S22 string + +func (s *S22) UnmarshalText(text []byte) error { + *s = S22("a") + return nil +} + +// Test to ensure that when a field that should be decoded into a type +// implementing the encoding.TextUnmarshaler interface is set to an empty value +// that the UnmarshalText method is utilized over other methods of decoding, +// especially including simply setting the zero value. +func TestTextUnmarshalerEmpty(t *testing.T) { + data := map[string][]string{ + "Value": []string{""}, // empty value + } + // Implements encoding.TextUnmarshaler, should use the type's + // UnmarshalText method. + s := struct { + Value S22 + }{} + decoder := NewDecoder() + if err := decoder.Decode(&s, data); err != nil { + t.Fatal("Error while decoding:", err) + } + expected := S22("a") + if expected != s.Value { + t.Errorf("Expected %v errors, got %v", expected, s.Value) + } +}