Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to unmarshal date using json-iterator. #313

Closed
aafreensheikh96 opened this issue Oct 16, 2018 · 4 comments
Closed

Unable to unmarshal date using json-iterator. #313

aafreensheikh96 opened this issue Oct 16, 2018 · 4 comments

Comments

@aafreensheikh96
Copy link

aafreensheikh96 commented Oct 16, 2018

I am trying to use a custom struct which implements the json.Unmarshaler interface as a key in a map(map[MyCustomType]bool). This fails when I am trying to use jsoniter but works correctly if I use the standard library json package. Minimal code example to reproduce the issue:

package main

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

    jsoniter "github.com/json-iterator/go"
)

type Date struct {
    time.Time
}

func (d *Date) UnmarshalJSON(b []byte) error {
    dateStr := string(b) // something like `"2017-08-20"`

    if dateStr == "null" {
        return nil
    }

    t, err := time.Parse(`"2006-01-02"`, dateStr)
    if err != nil {
        return fmt.Errorf("cant parse date: %#v", err)
    }

    d.Time = t
    return nil
}

func main() {
    data := []byte(`{
        "2018-12-12": true,
        "2018-12-13": true,
        "2018-12-14": true
    }`)

    v := map[Date]bool{}
    if err := json.Unmarshal(data, &v); err != nil {
        panic(fmt.Errorf("standard library unmarshal: %+v", err))
    }

    fmt.Printf("Unmarshalled value using standard library: %+v\n", v)

    if err := jsoniter.Unmarshal(data, &v); err != nil {
        panic(fmt.Errorf("jsoniter unmarshal: %+v", err))
    }

    fmt.Printf("%#v\n", v)
}

Output:

Unmarshalled value using standard library: map[2018-12-14 00:00:00 +0000 UTC:true 2018-12-12 00:00:00 +0000 UTC:true 2018-12-13 00:00:00 +0000 UTC:true]
panic: jsoniter unmarshal: textUnmarshalerDecoder: parsing time "2018-12-12" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "T", error found in #10 byte of ...|018-12-12": true,
  |..., bigger context ...|{
        "2018-12-12": true,
        "2018-12-13": true,
        "2018-|...
@aafreensheikh96
Copy link
Author

Doesn't still work on the latest version = "1.1.5"

@shatil
Copy link

shatil commented Oct 19, 2018

@aafreensheikh96 wow, jsoniter doesn't call Date.UnmarshalJSON at all, whereas encoding/json calls it three times, as expected.

(dlv) bp
Breakpoint unrecovered-panic at 0x102e760 for runtime.fatalpanic() /usr/local/Cellar/go/1.11.1/libexec/src/runtime/panic.go:681 (1)
	print runtime.curg._panic.arg
Breakpoint 1 at 0x11b8a3b for main.(*Date).UnmarshalJSON() ./main.go:15 (3)
Breakpoint jsoniter at 0x11b908d for main.main() ./main.go:45 (1)

Using Delve with your main.go in the current directory:

$ dlv debug
Type 'help' for list of commands.
(dlv) break Date.UnmarshalJSON
Breakpoint 1 set at 0x11b8a3b for main.(*Date).UnmarshalJSON() ./main.go:15
(dlv) break jsoniter main.go:45
Breakpoint jsoniter set at 0x11b908d for main.main() ./main.go:45

Then running it:

(dlv) continue
> main.(*Date).UnmarshalJSON() ./main.go:15 (hits goroutine(1):1 total:1) (PC: 0x11b8a3b)
    10:
    11:	type Date struct {
    12:		time.Time
    13:	}
    14:
=>  15:	func (d *Date) UnmarshalJSON(b []byte) error {
    16:		dateStr := string(b) // something like `"2017-08-20"`
    17:
    18:		if dateStr == "null" {
    19:			return nil
    20:		}
(dlv) continue
> main.(*Date).UnmarshalJSON() ./main.go:15 (hits goroutine(1):2 total:2) (PC: 0x11b8a3b)
    10:
    11:	type Date struct {
    12:		time.Time
    13:	}
    14:
=>  15:	func (d *Date) UnmarshalJSON(b []byte) error {
    16:		dateStr := string(b) // something like `"2017-08-20"`
    17:
    18:		if dateStr == "null" {
    19:			return nil
    20:		}
(dlv) continue
> main.(*Date).UnmarshalJSON() ./main.go:15 (hits goroutine(1):3 total:3) (PC: 0x11b8a3b)
    10:
    11:	type Date struct {
    12:		time.Time
    13:	}
    14:
=>  15:	func (d *Date) UnmarshalJSON(b []byte) error {
    16:		dateStr := string(b) // something like `"2017-08-20"`
    17:
    18:		if dateStr == "null" {
    19:			return nil
    20:		}
(dlv) continue
Unmarshalled value using standard library: map[2018-12-13 00:00:00 +0000 UTC:true 2018-12-14 00:00:00 +0000 UTC:true 2018-12-12 00:00:00 +0000 UTC:true]
> [jsoniter] main.main() ./main.go:45 (hits goroutine(1):1 total:1) (PC: 0x11b908d)
    40:			panic(fmt.Errorf("standard library unmarshal: %+v", err))
    41:		}
    42:
    43:		fmt.Printf("Unmarshalled value using standard library: %+v\n", v)
    44:
=>  45:		if err := jsoniter.Unmarshal(data, &v); err != nil {
    46:			panic(fmt.Errorf("jsoniter unmarshal: %+v", err))
    47:		}
    48:
    49:		fmt.Printf("%#v\n", v)
    50:	}
(dlv) continue
> [unrecovered-panic] runtime.fatalpanic() /usr/local/Cellar/go/1.11.1/libexec/src/runtime/panic.go:681 (hits goroutine(1):1 total:1) (PC: 0x102e760)
Warning: debugging optimized function
	runtime.curg._panic.arg: interface {}(string) "jsoniter unmarshal: textUnmarshalerDecoder: parsing time \"2018-1...+214 more"
   676:	// fatalpanic implements an unrecoverable panic. It is like fatalthrow, except
   677:	// that if msgs != nil, fatalpanic also prints panic messages and decrements
   678:	// runningPanicDefers once main is blocked from exiting.
   679:	//
   680:	//go:nosplit
=> 681:	func fatalpanic(msgs *_panic) {
   682:		pc := getcallerpc()
   683:		sp := getcallersp()
   684:		gp := getg()
   685:		var docrash bool
   686:		// Switch to the system stack to avoid any stack growth, which

@sudo-suhas
Copy link

@shatil Please note that unmarshaling works correctly when the Date data type is used as a value like so:

type myType struct {
	Date Date   `json:"date"`
	Text string `json:"text"`
}

@taowen taowen closed this as completed in 05d041d Oct 24, 2018
@sudo-suhas
Copy link

Thank you @taowen

zhenzou pushed a commit to zhenzou/jsoniter that referenced this issue Feb 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants