How to parse custom time format from json

says i have next json

{
    name: "John",
    birth_date: "1996-10-07"
}

and I want to decode it into the following structure

type Person struct {
    Name string `json:"name"`
    BirthDate time.Time `json:"birth_date"`
}

like this

person := Person{}

decoder := json.NewDecoder(req.Body);

if err := decoder.Decode(&person); err != nil {
    log.Println(err)
}

which gives me an error parsing time ""1996-10-07"" as ""2006-01-02T15:04:05Z07:00"": cannot parse """ as "T"

if I manually disassembled it, I would do it like

t, err := time.Parse("2006-01-02", "1996-10-07")

but when the time value is from json string , how can I get the decoder to parse it in the above format?

+11
source share
3 answers

This is the case when you need to implement custom functions of the marshal and demarche.

UnmarshalJSON(b []byte) error { ... }

MarshalJSON() ([]byte, error) { ... }

Following the example from the json package documentation for Golang, you will get something like:

// first create a type alias
type JsonBirthDate time.Time

// Add that to your struct
type Person struct {
    Name string 'json:"name"'
    BirthDate JsonBirthDate 'json:"birth_date"'
}

// imeplement Marshaler und Unmarshalere interface
func (j *JsonBirthDate) UnmarshalJSON(b []byte) error {
    s := strings.Trim(string(b), "\"")
    t, err := time.Parse("2006-01-02", s)
    if err != nil {
        return err
    }
    *j = JsonBirthDate(t)
    return nil
}

func (j JsonBirthDate) MarshalJSON() ([]byte, error) {
    return json.Marshal(j)
}

// Maybe a Format function for printing your date
func (j JsonBirthDate) Format(s string) string {
    t := time.Time(j)
    return t.Format(s)
}
+13
source

, , . ,, , json- jsontime:

import "github.com/liamylian/jsontime"

var json = jsontime.ConfigWithCustomTimeFormat

type Book struct {
    Id        int           'json:"id"'
    UpdatedAt *time.Time    'json:"updated_at" time_format:"sql_date" time_utc:"true"'
    CreatedAt time.Time     'json:"created_at" time_format:"sql_datetime" time_location:"UTC"'
}
+2

yyyy-MM-dd yyyy-MM-ddThh:mm:ss https://github.com/ah/date

, MarshalJSON UnmarshalJSON .

// MarshalJSON outputs JSON.
func (d YYYYMMDD) MarshalJSON() ([]byte, error) {
    return []byte("\"" + time.Time(d).Format(formatStringYYYYMMDD) + "\""), nil
}

// UnmarshalJSON handles incoming JSON.
func (d *YYYYMMDD) UnmarshalJSON(b []byte) (err error) {
    if err = checkJSONYYYYMMDD(string(b)); err != nil {
        return
    }
    t, err := time.ParseInLocation(parseJSONYYYYMMDD, string(b), time.UTC)
    if err != nil {
        return
    }
    *d = YYYYMMDD(t)
    return
}

. UTC, - .

I also found that decisions related to the use of the function time.Parseinternal mechanisms Go passed as the error message that clients do not find it helpful, for example: cannot parse "sdfdf-01-01" as "2006". This is only useful if you know that the server is written in Go and 2006is an example of a date format, so I am adding more readable error messages.

I also implemented an interface Stringerso that it was printed in log or debug messages.

+1
source

Source: https://habr.com/ru/post/1682216/


All Articles