Custom UnmarshalJSON for custom time format returning this {0 63082400645 <nil>} instead of time with ShouldBindJSON from Gin gonic

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

Custom UnmarshalJSON for custom time format returning this {0 63082400645 <nil>} instead of time with ShouldBindJSON from Gin gonic

问题

我有这个类型和处理程序

type Bday time.Time

func (mt *Bday) UnmarshalJSON(bs []byte) (err error) {
	var t time.Time
	layout := "2006-01-02T15:04:05Z0700" // RFC3339
	s := strings.Trim(string(bs), `"`)

	t, err = time.Parse(layout, s)
	if err != nil {
		return err
	}

	*mt = Bday(t)

	return
}

func (mt Bday) MarshalJSON() ([]byte, error) {
	timestamp := time.Time(mt)
	return json.Marshal(timestamp)
}

type LoginHandler struct {
	db *gorm.DB
}

func (l *LoginHandler) Signup(c *gin.Context) {
	// 验证姓名、姓氏、电子邮件、密码、性别、出生日期
	var user User


	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), 8)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	user.Password = string(hashedPassword)
	fmt.Println("User", user)
	// 保存到数据库
	l.db.Debug().Model(&models.User{}).Create(&user)

	// 返回代码201
	c.JSON(http.StatusCreated, gin.H{"message": "用户创建成功!"})
}

这是用户

type User struct {
Password  string    `json:"password"`
Email     string    `json:"email"`
Name      string    `json:"name"`
LastName  string    `json:"last_name"`
Bday      Bday      `json:"bday"`
Gender    string    `json:"gender"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt time.Time `json:"deleted_at"`
}

当我在处理程序中打印用户时,我得到了Bday字段的以下输出

{0 63082400645 <nil>}

这是完整的println

User {$2a$08$uTE7Llc6YM2owu.D6UWqpOcOVFHRFRrSxbkxWV4ecR72G6kK5/SNq d.n.m@gmail.com
Antonio Magalhães {0 63082400645 <nil>} M 0001-01-01 00:00:00 +0000 UTC 0001-01-01
00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}

我期望的是Bday是一个类似日期的东西
2001-01-01 00:00:00 +0000 UTC

有人可以帮我理解这个吗?

英文:

I have this type and handler

type Bday time.Time

func (mt *Bday) UnmarshalJSON(bs []byte) (err error) {
	var t time.Time
	layout := &quot;2006-01-02T15:04:05Z0700&quot; // RFC3339
	s := strings.Trim(string(bs), `&quot;`)

	t, err = time.Parse(layout, s)
	if err != nil {
		return err
	}

	*mt = Bday(t)

	return
}

func (mt Bday) MarshalJSON() ([]byte, error) {
	timestamp := time.Time(mt)
	return json.Marshal(timestamp)
}

type LoginHandler struct {
	db *gorm.DB
}

func (l *LoginHandler) Signup(c *gin.Context) {
	// Verify name, lastName, email, password, gender, birthDate
	var user User


	if err := c.ShouldBindJSON(&amp;user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), 8)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	user.Password = string(hashedPassword)
	fmt.Println(&quot;User&quot;, user)
	// Save to db
	l.db.Debug().Model(&amp;models.User{}).Create(&amp;user)

	// Return code 201
	c.JSON(http.StatusCreated, gin.H{&quot;message&quot;: &quot;User created successfully!&quot;})
}

This is the User

type User struct {
Password  string    `json:&quot;password&quot;`
Email     string    `json:&quot;email&quot;`
Name      string    `json:&quot;name&quot;`
LastName  string    `json:&quot;last_name&quot;`
Bday      Bday      `json:&quot;bday&quot;`
Gender    string    `json:&quot;gender&quot;`
CreatedAt time.Time `json:&quot;created_at&quot;`
UpdatedAt time.Time `json:&quot;updated_at&quot;`
DeletedAt time.Time `json:&quot;deleted_at&quot;`
}

When I print User in the handler I get this for the Bday field

{0 63082400645 &lt;nil&gt;}

This is the full println

User {$2a$08$uTE7Llc6YM2owu.D6UWqpOcOVFHRFRrSxbkxWV4ecR72G6kK5/SNq d.n.m@gmail.com
Antonio Magalh&#227;es {0 63082400645 &lt;nil&gt;} M 0001-01-01 00:00:00 +0000 UTC 0001-01-01
00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}

What I expected whas that Bday were something like a date
2001-01-01 00:00:00 +0000 UTC

Can somebody help me understand this?

答案1

得分: 1

你自定义的类型 Bday 既不满足 Formatter 接口,也不满足 Stringer 接口,因此会以复合结构的形式打印出来(底层 time.Time 结构的字段会逐个打印出来)。

一个简单的解决方法是实现一个 String() 方法,例如委托给 MarshalJSON

func (mt Bday) String() string {
    b, _ := mt.MarshalJSON()
    return string(b)
}

有关 fmt.Println 如何工作的更多详细信息,请参考 fmt 的文档。

英文:

Your custom type Bday satisfies neither Formatter nor Stringer interface, and thus gets printed as a compound struct (the fields of the underlying time.Time struct are printed individually).

An easy fix would be to implement a String() method, for example delegating to MarshalJSON:

func (mt Bday) String() string {
b, _ := mt.MarshalJSON()
return string(b)
}

For more details on how fmt.Println works refer to fmt package documentation.

huangapple
  • 本文由 发表于 2023年3月19日 23:10:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/75782962.html
匿名

发表评论

匿名网友

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

确定