Search code examples
gotimebindglide-golanggo-echo

How do I bind a date string to a struct?


type TestModel struct {
  Date     time.Time `json:"date" form:"date" gorm:"index"`
  gorm.Model
}

i'm using echo framwork, and I have a struct like the one above, and I get string data like '2021-09-27' , how can I bind it to the struct?

func CreateDiary(c echo.Context) error {
    var getData model.TestModel
    if err := (&echo.DefaultBinder{}).BindBody(c, &getData); err != nil {
        fmt.Print(err.Error())
    }
   return c.JSON(200, getData)
}

When I code like this, I get the following error:

code=400, message=parsing time "2021-09-27" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "T", internal=parsing time "2021-09-27" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "T"

I'm a golang beginner, can you show me a simple example??, please.

i'm using echo framwork


Solution

  • Here is list of available tags used in echo. If you want to parse from body, then use json

    • query - source is request query parameters.
    • param - source is route path parameter.
    • header - source is header parameter.
    • form - source is form. Values are taken from query and request body. Uses Go standard library form parsing.
    • json - source is request body. Uses Go json package for unmarshalling.
    • xml - source is request body. Uses Go xml package for unmarshalling.

    You need to wrap time.Time into custom struct and then implement json.Marshaler and json.Unmarshaler interfaces

    Example

    package main
    
    import (
        "fmt"
        "strings"
        "time"
    
        "github.com/labstack/echo/v4"
    )
    
    type CustomTime struct {
        time.Time
    }
    
    type TestModel struct {
        Date CustomTime `json:"date"`
    }
    
    func (t CustomTime) MarshalJSON() ([]byte, error) {
        date := t.Time.Format("2006-01-02")
        date = fmt.Sprintf(`"%s"`, date)
        return []byte(date), nil
    }
    
    func (t *CustomTime) UnmarshalJSON(b []byte) (err error) {
        s := strings.Trim(string(b), "\"")
    
        date, err := time.Parse("2006-01-02", s)
        if err != nil {
            return err
        }
        t.Time = date
        return
    }
    
    func main() {
        e := echo.New()
        e.POST("/test", CreateDiary)
        e.Logger.Fatal(e.Start(":1323"))
    }
    
    func CreateDiary(c echo.Context) error {
        var getData TestModel
        if err := (&echo.DefaultBinder{}).BindBody(c, &getData); err != nil {
            fmt.Print(err.Error())
        }
        return c.JSON(200, getData)
    }
    

    test

    curl -X POST http://localhost:1323/test -H 'Content-Type: application/json' -d '{"date":"2021-09-27"}'