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

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

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

问题

我有这个类型和处理程序

  1. type Bday time.Time
  2. func (mt *Bday) UnmarshalJSON(bs []byte) (err error) {
  3. var t time.Time
  4. layout := "2006-01-02T15:04:05Z0700" // RFC3339
  5. s := strings.Trim(string(bs), `"`)
  6. t, err = time.Parse(layout, s)
  7. if err != nil {
  8. return err
  9. }
  10. *mt = Bday(t)
  11. return
  12. }
  13. func (mt Bday) MarshalJSON() ([]byte, error) {
  14. timestamp := time.Time(mt)
  15. return json.Marshal(timestamp)
  16. }
  17. type LoginHandler struct {
  18. db *gorm.DB
  19. }
  20. func (l *LoginHandler) Signup(c *gin.Context) {
  21. // 验证姓名、姓氏、电子邮件、密码、性别、出生日期
  22. var user User
  23. if err := c.ShouldBindJSON(&user); err != nil {
  24. c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  25. return
  26. }
  27. hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), 8)
  28. if err != nil {
  29. c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
  30. return
  31. }
  32. user.Password = string(hashedPassword)
  33. fmt.Println("User", user)
  34. // 保存到数据库
  35. l.db.Debug().Model(&models.User{}).Create(&user)
  36. // 返回代码201
  37. c.JSON(http.StatusCreated, gin.H{"message": "用户创建成功!"})
  38. }

这是用户

  1. type User struct {
  2. Password string `json:"password"`
  3. Email string `json:"email"`
  4. Name string `json:"name"`
  5. LastName string `json:"last_name"`
  6. Bday Bday `json:"bday"`
  7. Gender string `json:"gender"`
  8. CreatedAt time.Time `json:"created_at"`
  9. UpdatedAt time.Time `json:"updated_at"`
  10. DeletedAt time.Time `json:"deleted_at"`
  11. }

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

{0 63082400645 <nil>}

这是完整的println

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

  1. type Bday time.Time
  2. func (mt *Bday) UnmarshalJSON(bs []byte) (err error) {
  3. var t time.Time
  4. layout := &quot;2006-01-02T15:04:05Z0700&quot; // RFC3339
  5. s := strings.Trim(string(bs), `&quot;`)
  6. t, err = time.Parse(layout, s)
  7. if err != nil {
  8. return err
  9. }
  10. *mt = Bday(t)
  11. return
  12. }
  13. func (mt Bday) MarshalJSON() ([]byte, error) {
  14. timestamp := time.Time(mt)
  15. return json.Marshal(timestamp)
  16. }
  17. type LoginHandler struct {
  18. db *gorm.DB
  19. }
  20. func (l *LoginHandler) Signup(c *gin.Context) {
  21. // Verify name, lastName, email, password, gender, birthDate
  22. var user User
  23. if err := c.ShouldBindJSON(&amp;user); err != nil {
  24. c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: err.Error()})
  25. return
  26. }
  27. hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), 8)
  28. if err != nil {
  29. c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: err.Error()})
  30. return
  31. }
  32. user.Password = string(hashedPassword)
  33. fmt.Println(&quot;User&quot;, user)
  34. // Save to db
  35. l.db.Debug().Model(&amp;models.User{}).Create(&amp;user)
  36. // Return code 201
  37. c.JSON(http.StatusCreated, gin.H{&quot;message&quot;: &quot;User created successfully!&quot;})
  38. }

This is the User

  1. type User struct {
  2. Password string `json:&quot;password&quot;`
  3. Email string `json:&quot;email&quot;`
  4. Name string `json:&quot;name&quot;`
  5. LastName string `json:&quot;last_name&quot;`
  6. Bday Bday `json:&quot;bday&quot;`
  7. Gender string `json:&quot;gender&quot;`
  8. CreatedAt time.Time `json:&quot;created_at&quot;`
  9. UpdatedAt time.Time `json:&quot;updated_at&quot;`
  10. DeletedAt time.Time `json:&quot;deleted_at&quot;`
  11. }

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

{0 63082400645 &lt;nil&gt;}

This is the full println

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

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

有关 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:

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

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:

确定