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: Json marshaler seems to not marshal correctly if there is an embedded struct with custom marshaller #46799

Closed
sraghav1 opened this issue Jun 17, 2021 · 3 comments

Comments

@sraghav1
Copy link

sraghav1 commented Jun 17, 2021

What version of Go are you using (go version)?

$ go version
go1.16.2

Does this issue reproduce with the latest release?

Yes. Checked using go1.16.5 on play.golang.org.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/sraghav1/.cache/go-build"
GOENV="/home/sraghav1/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/sraghav1/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/sraghav1/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.2"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/sraghav1/src/xeon-health/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build904965005=/tmp/go-build -gno-record-gcc-switches"

What did you do?

  • Create a struct C which embeds another struct A and adds additional fields
  • The struct A has a custom marshaler with pointer receiver. (func (a *A) MarshalJSON() ([]byte, error) )
  • Marshalling a pointer to an object of type C, returns marshaled JSON with only A.

Example: https://play.golang.org/p/euugvbFXI76

type A struct {
	X int
	Y string
	Z float64
}

type C struct {
	X2 int
	A
}

func (a *A) MarshalJSON() ([]byte, error) {
	type aliasA A
	a2:=aliasA(*a) 
	return json.Marshal(a2) // Essentially a no-op custom marshaler to illustrate the problem
}
	
func main() {	
	a := A{X:10, Y:"faster", Z:2.43}
	c := C{X2:101, A:a}
			
	jc, _ := json.Marshal(&c)
	fmt.Println(string(jc))		
}

Additional notes

What did you expect to see?

{"X2":101,"X":10,"Y":"faster","Z":2.43}

What did you see instead?

{"X":10,"Y":"faster","Z":2.43}

@seankhliao
Copy link
Member

seankhliao commented Jun 17, 2021

The UnmarshalJSON MarshalJSON method is promoted from A to C because of embedding

Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.

For questions please refer to https://github.com/golang/go/wiki/Questions

@sraghav1
Copy link
Author

sraghav1 commented Jun 17, 2021

I believe this is not a general discusison or a doubt I am trying to ask. I can take it to other forums but will be great if you can check the issue description again.

I am not talking about UnmarshalJSON but MarshalJSON.

The problem is not it is getting promoted from A to C, but it is NOT getting promoted as expected.

It gets promoted as expected when a dummy custom marshaller is added to C which is expected. But it does not get promoted if there is not custom marshaler.

@seankhliao
Copy link
Member

Still works the same, embedded fields/methods are promoted if they don't conflict

@golang golang locked and limited conversation to collaborators Jun 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants