How to parse non standard time format from json

后端 未结 3 1506
梦如初夏
梦如初夏 2020-12-24 03:32

lets say i have the following json

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

and i want to decode it into the following struct

相关标签:
3条回答
  • 2020-12-24 03:48

    If there are lots of struct and you just implement custom marshal und unmarshal functions, that's a lot of work to do so. You can use another lib instead,such as a json-iterator extension 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"`
    }
    
    0 讨论(0)
  • 2020-12-24 03:50

    That's a case when you need to implement custom marshal and unmarshal functions.

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

    By following the example in the Golang documentation of json package you 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"`
    }
    
    // Implement Marshaler and Unmarshaler 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)
    }
    
    0 讨论(0)
  • 2020-12-24 04:10

    I wrote a package for handling yyyy-MM-dd and yyyy-MM-ddThh:mm:ss dates at https://github.com/a-h/date

    It uses the type alias approach in the answer above, then implements the MarshalJSON and UnmarshalJSON functions with a few alterations.

    // 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
    }
    

    It's important to parse in the correct timezone. My code assumes UTC, but you may wish to use the computer's timezone for some reason.

    I also found that solutions which involved using the time.Parse function leaked Go's internal mechanisms as an error message which clients didn't find helpful, for example: cannot parse "sdfdf-01-01" as "2006". That's only useful if you know that the server is written in Go, and that 2006 is the example date format, so I put in more readable error messages.

    I also implemented the Stringer interface so that it gets pretty printed in log or debug messages.

    0 讨论(0)
提交回复
热议问题