網頁

2022/1/19

Golang 自訂日期格式轉換JSON為time.Time unmarshal Request JSON to time.Time by custom format

Go net/http handler依自訂日期時間格式接收POST請求的JSON中的日期時間字串並轉為time.Time範例。


範例環境:

  • Go 1.17


Client發送請求的JSON字串如下。日期時間格式為yyyy-MM-dd格式。

{
  "id": 1,
  "name": "john",
  "age": 33,
  "createdDate": "2022-01-19"
}

由於time.Time接收的字串格式必須是RFC3339格式(e.g. yyyy-MM-ddThh:mm:ssZ),所以下面自訂接收的格式為yyyy-MM-dd


一 - 實作 json.Unmarshaler, json.Marshaler

Employee為JSON字串要轉成的struct。定義type Datetime.Time並實作json.Unmarshalerjson.Marshaler介面。

實作Unmarshaler.UnmarshalJSON()自訂json轉換為物件的邏輯;
實作Marshaler.MarshalJSON()自訂轉換物件為json的邏輯。

main.go

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strings"
    "time"
)

type Date time.Time

var df = "2006-01-02"

func (d *Date) UnmarshalJSON(b []byte) error {
    s := strings.Trim(string(b), "\"")
    t, err := time.Parse(df, s)
    if err != nil {
        return err
    }
    *d = Date(t)
    return nil
}

func (d Date) MarshalJSON() ([]byte, error) {
    t := time.Time(d)
    s := t.Format(df)
    return json.Marshal(s)
}

type Employee struct {
    Id          int
    Name        string
    Age         int
    CreatedDate Date
}

func main() {
    http.HandleFunc("/employee", func(rw http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodPost:
            var emp Employee
            if err := json.NewDecoder(r.Body).Decode(&emp); err != nil {
                panic(err)
            }
            fmt.Println(time.Time(emp.CreatedDate)) // 2021-01-19 00:00:00 +0000 UTC
            json.NewEncoder(rw).Encode(emp)
        default:
            http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })

    http.ListenAndServe(":8080", nil)
}


github


測試

啟動應用程式後在命令列以cURL發出以下請求。

$ curl -X POST "http://localhost:8080/employee" -H 'content-type: application/json' -d '{"id": 1, "name": "john", "age": 33, "createdDate": "2021-01-19"}'

在console印出以下。

2021-01-19 00:00:00 +0000 UTC

回應結果如下:

{"Id":1,"Name":"john","Age":33,"CreatedDate":"2021-01-19"}




二 - 實作 encoding.TextMarshaler, encoding.UnmarshalText

Employee為JSON字串要轉成的struct。定義type Datetime.Time並實作encoding.UnmarshalTextencoding.Marshaler介面。

實作TextUnmarshaler.UnmarshalText()自訂text轉換為物件的邏輯;
實作TextMarshaler.MarshalText()自訂轉換物件為text的邏輯。

main.go

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "time"
)

var df = "2006-01-02"

type Date time.Time

func (d *Date) UnmarshalText(text []byte) error {
    t, err := time.Parse(df, string(text))
    if err != nil {
        return err
    }
    *d = Date(t)
    return nil
}

func (d Date) MarshalText() (text []byte, err error) {
    s := time.Time(d).Format(df)
    return []byte(s), nil
}

func (c Date) String() string {
    return time.Time(c).Format(df)
}

type Employee struct {
    Id          int
    Name        string
    Age         int
    CreatedDate Date
}

func main() {
    http.HandleFunc("/employee", func(rw http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodPost:
            var emp Employee
            if err := json.NewDecoder(r.Body).Decode(&emp); err != nil {
                panic(err)
            }
            fmt.Println(emp.CreatedDate) // 2021-01-19
            json.NewEncoder(rw).Encode(emp)
        default:
            http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })

    http.ListenAndServe(":8080", nil)
}

github


測試

啟動應用程式後在命令列以cURL發出以下請求。

$ curl -X POST "http://localhost:8080/employee" -H 'content-type: application/json' -d '{"id": 1, "name": "john", "age": 33, "createdDate": "2021-01-19"}'

在console印出以下。

2021-01-19

回應結果如下:

{"Id":1,"Name":"john","Age":33,"CreatedDate":"2021-01-19"}


沒有留言:

張貼留言