json unmarshal time that isn't in RFC 3339 format

JsonGo

Json Problem Overview


What is the appropriate way to handle deserialization of different time formats in Go? The encoding/json package seems to be entirely rigid in only accepted RFC 3339. I can deserialize into a string, transform that into RFC 3339 and then unmarshal it but I don't really want to do that. Any better solutions?

Json Solutions


Solution 1 - Json

You will have to implement the json.Marshaler / json.Unmarshaler interfaces on a custom type and use that instead, an example:

type CustomTime struct {
	time.Time
}

const ctLayout = "2006/01/02|15:04:05"

func (ct *CustomTime) UnmarshalJSON(b []byte) (err error) {
    s := strings.Trim(string(b), "\"")
    if s == "null" {
	   ct.Time = time.Time{}
	   return
    }
    ct.Time, err = time.Parse(ctLayout, s)
    return
}

func (ct *CustomTime) MarshalJSON() ([]byte, error) {
  if ct.Time.UnixNano() == nilTime {
	return []byte("null"), nil
  }
  return []byte(fmt.Sprintf("\"%s\"", ct.Time.Format(ctLayout))), nil
}

var nilTime = (time.Time{}).UnixNano()
func (ct *CustomTime) IsSet() bool {
	return ct.UnixNano() != nilTime
}

type Args struct {
	Time CustomTime
}

var data = `
	{"Time": "2014/08/01|11:27:18"}
`

func main() {
	a := Args{}
	fmt.Println(json.Unmarshal([]byte(data), &a))
	fmt.Println(a.Time.String())
}

edit: added CustomTime.IsSet() to check it was actually set or not, for future reference.

Solution 2 - Json

The encoding/decoding is done by time.Time itself, in the MarshalJSON and UnamrshalJSON methods. You could create your own time.Time type and override those functions to work with the json however you want.

type Time struct {
	time.Time
}

// returns time.Now() no matter what!
func (t *Time) UnmarshalJSON(b []byte) error {
	// you can now parse b as thoroughly as you want

	*t = Time{time.Now()}
	return nil
}

type Config struct {
	T Time
}

func main() {
	c := Config{}

	json.Unmarshal([]byte(`{"T": "bad-time"}`), &c)

	fmt.Printf("%+v\n", c)
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionevanmcdonnalView Question on Stackoverflow
Solution 1 - JsonOneOfOneView Answer on Stackoverflow
Solution 2 - JsonJimBView Answer on Stackoverflow