Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parsing time """" as ""2006-01-02T15:04:05Z07:00"": cannot parse """ as "2006"

Tags:

go

I am trying to unmarshal some json into a struct and have the following:

package main

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

type Added struct {
    Added *time.Time `json:"added"`
}

func main() {
    st := strings.NewReader(`{"added": ""}`)

    a := &Added{}
    err := json.NewDecoder(st).Decode(&a)
    if err != nil {
        panic(err)
    }

    fmt.Println(a)

}

Running the above results in:

panic: parsing time """" as ""2006-01-02T15:04:05Z07:00"": cannot parse """ as "2006"

Ok, so I try a custom marshaller:

package main

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

type Added struct {
    Added *MyTime `json:"added"`
}

func main() {
    st := strings.NewReader(`{"added": ""}`)

    a := &Added{}
    err := json.NewDecoder(st).Decode(&a)
    if err != nil {
        panic(err)
    }

    fmt.Println(a)

}

type MyTime struct {
    *time.Time
}

func (m *MyTime) UnmarshalJSON(data []byte) error {
    // Ignore null, like in the main JSON package.
    if string(data) == "null" || string(data) == `""` {
        return nil
    }
    // Fractional seconds are handled implicitly by Parse.
    tt, err := time.Parse(`"`+time.RFC3339+`"`, string(data))
    *m = MyTime{&tt}
    return err
}

I then get:

&{%!v(PANIC=runtime error: invalid memory address or nil pointer dereference)}

Ok, now what do I do? I'd simply like to handle the "" value from the json.

My playground with the complete example is found.

like image 718
user_78361084 Avatar asked Feb 10 '19 16:02

user_78361084


2 Answers

Package time

import "time"

type Time

A Time represents an instant in time with nanosecond precision.

Programs using times should typically store and pass them as values, not pointers. That is, time variables and struct fields should be of type time.Time, not *time.Time.


I just kept fixing likely problems, for example, time.Time, not *time.Time, a real date, and so on, until I got a reasonable result:

package main

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

type MyTime struct {
    time.Time
}

func (m *MyTime) UnmarshalJSON(data []byte) error {
    // Ignore null, like in the main JSON package.
    if string(data) == "null" || string(data) == `""` {
        return nil
    }
    // Fractional seconds are handled implicitly by Parse.
    tt, err := time.Parse(`"`+time.RFC3339+`"`, string(data))
    *m = MyTime{tt}
    return err
}

type Added struct {
    Added MyTime `json:"added"`
}

func main() {
    st := strings.NewReader(`{"added": "2012-04-23T18:25:43.511Z"}`)

    var a Added
    err := json.NewDecoder(st).Decode(&a)
    if err != nil {
        panic(err)
    }
    fmt.Println(a)
}

Playground: https://play.golang.org/p/Uusdp3DkXDU

Output:

{2012-04-23 18:25:43.511 +0000 UTC}

With an empty ("") date string, the time.Time zero value, 0001-01-01 00:00:00 +0000 UTC:

Playground: https://play.golang.org/p/eQoEyqBlhg2

Output:

{0001-01-01 00:00:00 +0000 UTC}

Use the time IsZero method to test for the zero value.

func (Time) IsZero

func (t Time) IsZero() bool

IsZero reports whether t represents the zero time instant, January 1, year 1, 00:00:00 UTC.

like image 165
peterSO Avatar answered Jan 01 '23 10:01

peterSO


I think you were very close to the solution with your custom marshaller. Maybe just revert to normal decoding for normal dates. This may help:

type MyTime time.Time

func (m *MyTime) UnmarshalJSON(data []byte) error {
    // Ignore null, like in the main JSON package.
    if string(data) == "null" || string(data) == `""` {
        return nil
    }
    return json.Unmarshal(data, (*time.Time)(m))
}
like image 26
Andrew W. Phillips Avatar answered Jan 01 '23 12:01

Andrew W. Phillips