在Go中解析奇怪的JSON日期格式

huangapple go评论82阅读模式
英文:

Parsing odd JSON date formats in Go

问题

我正在调用一个旧的 API,它返回的对象形式如下:

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

我使用以下定义的结构体:

type Values struct{
  Value int
  Time time.Time
}

但是我得到了一个 &time.ParseError。作为 Go 的初学者,有没有办法让我定义如何序列化/反序列化这个对象?最终,我确实希望它作为一个 time.Time 对象。

这个日期格式似乎是一个较旧的 .NET 格式。我也无法更改输出。

英文:

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.

答案1

得分: 5

你需要在你的Values结构体上实现json的Unmarshaler接口。

// UnmarshalJSON 实现了json的Unmarshaler接口
func (v *Values) UnmarshalJSON(data []byte) error {
    // 创建一个临时结构体进行解析
    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

    // 去除时间戳的前缀和后缀
    s := strings.TrimSuffix(strings.TrimPrefix(tmp.Time, "/Date("), ")/")

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

    // 使用时间戳创建并赋值时间
    v.Time = time.Unix(i/1000, 0)

    return nil
}

可以查看这个可运行的示例

英文:

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.

答案2

得分: 1

另一种方法是定义一个自定义类型来表示时间,而不是手动创建一个临时结构体。

此外,嵌入time.Time类型可以更容易地访问其定义的所有函数,比如.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

英文:

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) &lt; 9 || data[6] != &#39;(&#39; || data[len(data)-3] != &#39;)&#39; {
		return fmt.Errorf(&quot;unexpected input %q&quot;, 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
}

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2014年10月6日 08:22:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/26208591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定