Decoding into interface bug
When I tried to unmarshal bytes into a struct hidden under a specific interface, "go-json" failed to unmarshal it. At the same time, go standard lib or json-iterator feels just fine with this approach.
Since you claim that your library is 100% compatible with the standard library, it makes sense to fix this bug or to change your README and add this exact case.
Code to reproduce the bug:
package main
import (
"fmt"
"github.com/goccy/go-json"
)
type EsDocument interface {
IndexName() string
}
type Property struct {
Name string `json:"name"`
}
func (p Property) IndexName() string {
return "properties"
}
func main() {
b := []byte(`{"name":"Test Property to remove"}`)
p := Property{}
unmarshallInterface(b, &p)
fmt.Println(p)
}
func unmarshallInterface(body []byte, doc EsDocument) {
if err := json.Unmarshal(body, &doc); err != nil {
panic(err)
}
}
Output
$ go run main.go
panic: json: cannot unmarshal main.EsDocument into Go value of type main.EsDocument
goroutine 1 [running]:
main.unmarshallInterface(...)
/home/grbit/ssd/go/src/tst/main.go:31
main.main()
/home/grbit/ssd/go/src/tst/main.go:24 +0x16d
exit status 2
If you change doc type name from EsDocument to just interface{} it'll work just fine.
package main
import (
"fmt"
"github.com/goccy/go-json"
)
type Property struct {
Name string `json:"name"`
}
func main() {
b := []byte(`{"name":"Test Property to remove"}`)
p := Property{}
unmarshallInterface(b, &p)
fmt.Println(p)
}
func unmarshallInterface(body []byte, doc interface{}) {
if err := json.Unmarshal(body, &doc); err != nil {
panic(err)
}
}
Output
$ go run main.go
{Test Property to remove}
Solved!
Hello @goccy, in #406 you said that you would fix this issue, the fix seems to be pretty small by itself, is there any chance you will do that any time soon? Thanks!
@mymmrac are you sure that the bug persists with the latest version? For me it works now. Maybe your case is a little bit different? If so, it would be great if you could provide a test case reproducing the problem.
@GRbit yes, it reproduces, here is an example:
package main
import (
// "encoding/json"
"fmt"
"github.com/goccy/go-json"
)
func main() {
s := Something{}
s.Thing = &ThingA{}
err := json.Unmarshal([]byte(`{"thing": {"a": 1}}`), &s)
if err != nil {
panic(err)
}
fmt.Println(s.Thing)
}
type Something struct {
Thing Thing `json:"thing"`
}
type Thing interface {
F()
}
type ThingA struct {
A int `json:"a"`
}
func (t *ThingA) F() {}
With github.com/goccy/go-json - current master df897ae
panic: json: cannot unmarshal main.Thing into Go struct field Something.Thing of type main.Thing
With encoding/json - no issues, parsed as expected (s.Thing.A == 1)
With this changes it works (from PR that was closed, #406):
replace github.com/goccy/go-json => github.com/cmetallo42/go-json v0.0.0-20221114111108-7fed434e8044
@mymmrac Indeed, you are right.
For some reason I thought that at some point it was fixed in goccy repository. Thank you for bringing this up again.