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

encoding/json: Unmarshal an interface pointer bug #21494

Closed
XingLong9630 opened this issue Aug 17, 2017 · 2 comments

Comments

Projects
None yet
4 participants
@XingLong9630
Copy link

commented Aug 17, 2017

go version
go1.8.3 linux/amd64

go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/xing/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build248645349=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

type Test struct{
	A string
	B string
}

func main(){
	a := Test{"12","23"}
	b := reflect.New(reflect.TypeOf(a)).Elem().Interface()
	c,err := json.Marshal(a)
	if err != nil {
		log.Fatal(err)
	}
	json.Unmarshal(c,&b)
	fmt.Printf("%#v", b)
}
result : 
map[string]interface {}{"A":"12", "B":"23"}

So we can see json.Unmarshal will change the type of 'b' from Test to map[string]interface{}

Reason :
encoding/json/decode.go function indirect (line 439)

if v.Kind() == reflect.Interface && !v.IsNil() {
			e := v.Elem()
			if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
				v = e
				continue
			}
                        //maybe you can check the e.Kind() here
		}

Thanks

@cznic

This comment has been minimized.

Copy link
Contributor

commented Aug 17, 2017

@ianlancetaylor ianlancetaylor changed the title json: Unmarshal an interface pointer bug encoding/json: Unmarshal an interface pointer bug Aug 17, 2017

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Aug 17, 2017

This is happening because the type of b is interface{}, so the type of &b, which you pass to json.Unmarshal, is type *interface{}. Unmarshal isn't changing the type, it's using the type you give it.

Closing because I don't think there is anything to fix here. Please comment if you disagree.

@golang golang locked and limited conversation to collaborators Aug 17, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.