Beau Trepp
Beau Trepp

Reputation: 2750

Parsing odd JSON date formats in Go

I'm calling a older api, and its returning objects in the form of.

{ value: 1, time: "/Date(1412321990000)/" }

Using a struct defined with

type Values struct{
  Value int
  Time time.Time
}

Gives me a &time.ParseError. I'm a beginner at Go, is there a way for me to define how this should be serialized/deserialized?. Ultimately I do want it as a time.Time object.

This date format seems to be an older .NET format too. Can't really get the output changed either.

Upvotes: 3

Views: 254

Answers (2)

OneOfOne
OneOfOne

Reputation: 99225

A different approach is to define a custom type for the time instead of manually creating a temp struct.

Also embedding time.Time makes it easier to access all the functions defined on it, like .String().

type WeirdTime struct{ time.Time }

type Value struct {
    Value int
    Time  WeirdTime
}

func (wt *WeirdTime) UnmarshalJSON(data []byte) error {
    if len(data) < 9 || data[6] != '(' || data[len(data)-3] != ')' {
        return fmt.Errorf("unexpected input %q", data)
    }
    t, err := strconv.ParseInt(string(data[7:len(data)-3]), 10, 64)
    if err != nil {
        return err
    }
    wt.Time = time.Unix(t/1000, 0)
    return nil
}

playground

Upvotes: 1

jmaloney
jmaloney

Reputation: 12280

You need to implement the json Unmarshaler interface on your Values struct.

// UnmarshalJSON implements json's Unmarshaler interface
func (v *Values) UnmarshalJSON(data []byte) error {
    // create tmp struct to unmarshal into
    var tmp struct {
        Value int    `json:"value"`
        Time  string `json:"time"`
    }
    if err := json.Unmarshal(data, &tmp); err != nil {
        return err
    }

    v.Value = tmp.Value

    // trim out the timestamp
    s := strings.TrimSuffix(strings.TrimPrefix(tmp.Time, "/Date("), ")/")

    i, err := strconv.ParseInt(s, 10, 64)
    if err != nil {
        return err
    }

    // create and assign time using the timestamp
    v.Time = time.Unix(i/1000, 0)

    return nil
}

Check out this working example.

Upvotes: 5

Related Questions