From e5f4f566ed12f1ba5887bf9448b44f764899a42e Mon Sep 17 00:00:00 2001 From: Jed Borovik Date: Thu, 10 Sep 2015 13:36:31 -0400 Subject: [PATCH] Add unmarshalling null.Time from map[string]interface{} --- time.go | 23 ++++++++++++++++++----- time_test.go | 12 ++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/time.go b/time.go index 741e2a4..d69f28c 100644 --- a/time.go +++ b/time.go @@ -71,16 +71,29 @@ func (t Time) MarshalJSON() ([]byte, error) { } // UnmarshalJSON implements json.Unmarshaler. -// It supports time, string and null input. +// It supports string, map[string]interface{}, +// and null input. func (t *Time) UnmarshalJSON(data []byte) error { var err error var v interface{} - json.Unmarshal(data, &v) + if err = json.Unmarshal(data, &v); err != nil { + return err + } switch x := v.(type) { - case time.Time: - t.Time = x case string: - t.Time, err = time.Parse(time.RFC3339, x) + err = t.Time.UnmarshalJSON(data) + case map[string]interface{}: + ti, tiOK := x["Time"].(string) + valid, validOK := x["Valid"].(bool) + if !tiOK || !validOK { + err = fmt.Errorf("json: unmarshalling map[string]interface{} into Go value of type null.Time requires key \"Time\" to be of type string and key \"Valid\" to be of type bool; found %T and %T, respectively", x["Time"], x["Valid"]) + break + } + err = t.Time.UnmarshalJSON([]byte(`"` + ti + `"`)) + t.Valid = valid + if err == nil && t.Valid == false { + return nil // Return here to prevent `Valid` from being set to true based on nil error below. + } case nil: t.Valid = false return nil diff --git a/time_test.go b/time_test.go index 390dc08..aebfec1 100644 --- a/time_test.go +++ b/time_test.go @@ -11,6 +11,8 @@ var ( timeJSON = []byte(`"` + timeString + `"`) blankTimeJSON = []byte(`null`) timeValue, _ = time.Parse(time.RFC3339, timeString) + timeMap = []byte(`{"Time":"2012-12-21T21:21:21Z","Valid":true}`) + invalidMap = []byte(`{"Time":"0001-01-01T00:00:00Z","Valid":false}`) ) func TestUnmarshalTimeString(t *testing.T) { @@ -23,6 +25,16 @@ func TestUnmarshalTimeString(t *testing.T) { err = json.Unmarshal(blankTimeJSON, &blank) maybePanic(err) assertNullTime(t, blank, "blank time json") + + var fromMap Time + err = json.Unmarshal(timeMap, &fromMap) + maybePanic(err) + assertTime(t, fromMap, "map time json") + + var invalid Time + err = json.Unmarshal(invalidMap, &invalid) + maybePanic(err) + assertNullTime(t, invalid, "map invalid time json") } func TestMarshalTime(t *testing.T) {