Golang JSON Marshal/Unmarshal postgres now()

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

Golang JSON Marshal/Unmarshal postgres now()

问题

我正在使用PostgreSQL的now()函数作为created时间戳的默认值,生成的结果如下:

 id | user_id | title | slug | content |          created           
----+---------+-------+------+---------+----------------------------
  1 |       1 | Foo   | foo  | bar     | 2014-12-16 19:41:31.428883
  2 |       1 | Bar   | bar  | whiz    | 2014-12-17 02:03:31.566419

我尝试使用json.Marshaljson.Unmarshal,但出现了以下错误:

将时间“2014-12-16 19:41:31.428883”解析为“2006-01-02T15:04:05Z07:00”时出错:无法将“ 19:41:31.428883”解析为“T”

因此,我决定尝试创建一个自定义的时间类型,但似乎无法使其正常工作。

Post.go

package models

type Post struct {
	Id      int    `json:"id"`
	UserId  int    `json:"user_id"`
	Title   string `json:"title"`
	Slug    string `json:"slug"`
	Content string `json:"content"`
	Created Tick   `json:"created"`
	User    User   `json:"user"`
}

Tick.go

package models

import (
	"fmt"
	"time"
)

type Tick struct {
	time.Time
}

var format = "2006-01-02T15:04:05.999999-07:00"

func (t *Tick) MarshalJSON() ([]byte, error) {
	return []byte(t.Time.Format(format)), nil
}

func (t *Tick) UnmarshalJSON(b []byte) (err error) {
	b = b[1 : len(b)-1]
	t.Time, err = time.Parse(format, string(b))
	return
}

非常感谢您的帮助,运行我在这里编写的代码会出现以下错误:

json: 对于类型models.Tick,调用MarshalJSON时出错:在顶级值之后有无效字符'0'

英文:

I'm using postgres' now() as a default for my created timestamp, which is generates this:

 id | user_id | title | slug | content |          created           
----+---------+-------+------+---------+----------------------------
  1 |       1 | Foo   | foo  | bar     | 2014-12-16 19:41:31.428883
  2 |       1 | Bar   | bar  | whiz    | 2014-12-17 02:03:31.566419

I tried to use json.Marshal and json.Unmarshal and ended up getting this error:

parsing time ""2014-12-16 19:41:31.428883"" as ""2006-01-02T15:04:05Z07:00"": cannot parse " 19:41:31.428883"" as "T"

So I decided to try and create a custom time, but can't seem to get anything working.

Post.go

package models

type Post struct {
	Id      int    `json:"id"`
	UserId  int    `json:"user_id"`
	Title   string `json:"title"`
	Slug    string `json:"slug"`
	Content string `json:"content"`
	Created Tick   `json:"created"`
	User    User   `json:"user"`
}

Tick.go

package models

import (
	"fmt"
	"time"
)

type Tick struct {
	time.Time
}

var format = "2006-01-02T15:04:05.999999-07:00"

func (t *Tick) MarshalJSON() ([]byte, error) {
	return []byte(t.Time.Format(format)), nil
}

func (t *Tick) UnmarshalJSON(b []byte) (err error) {
	b = b[1 : len(b)-1]
	t.Time, err = time.Parse(format, string(b))
	return
}

Any help would be much appreciated, running what I've wrote here gives me this:

json: error calling MarshalJSON for type models.Tick: invalid character '0' after top-level value

答案1

得分: 1

JSON要求字符串要用引号括起来(在JSON中,日期是一个字符串),但是你的MarshalJSON函数返回的是一个没有引号的字符串。

我稍微修改了你的代码,现在它可以正常工作了:

package models

import (
    "fmt"
    "time"
)

type Tick struct {
    time.Time
}

var format = "2006-01-02T15:04:05.999999-07:00"

func (t *Tick) MarshalJSON() ([]byte, error) {
    // 使用`append`来避免字符串拼接
    b := make([]byte, 0, len(format)+2)
    b = append(b, '"')
    b = append(b, t.Time.Format(format)...)
    b = append(b, '"')
    return b, nil
}

func (t *Tick) UnmarshalJSON(b []byte) (err error) {
    b = b[1 : len(b)-1]
    t.Time, err = time.Parse(format, string(b))
    return
}

希望对你有帮助!

英文:

JSON requires strings to be quoted (and in JSON a date is a string), however your MarshalJSON function returns an unquoted string.

I've slightly amended your code and it works fine now:

package models

import (
    "fmt"
    "time"
)

type Tick struct {
    time.Time
}

var format = "2006-01-02T15:04:05.999999-07:00"

func (t *Tick) MarshalJSON() ([]byte, error) {
    // using `append` to avoid string concatenation
    b := make([]byte, 0, len(format)+2)
    b = append(b, '"')
    b = append(b, t.Time.Format(format)...)
    b = append(b, '"')
    return b, nil
}

func (t *Tick) UnmarshalJSON(b []byte) (err error) {
    b = b[1 : len(b)-1]
    t.Time, err = time.Parse(format, string(b))
    return
}

答案2

得分: 0

看起来你正在使用错误的格式。Postgres使用RFC 3339格式,该格式已在time包中定义。

以下是正确的写法:

time.Parse(time.RFC3339, string(b))
英文:

it's seems like you're using the wrong format. Postgres uses RFC 3339, which is already defined in the time package.
This should work:

<!-- language: lang-go -->

time.Parse(time.RFC3339, string(b))

huangapple
  • 本文由 发表于 2014年12月17日 11:15:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/27517752.html
匿名

发表评论

匿名网友

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

确定