Skip to content

encoding/json/v2: inline struct fields don't work with MarshalToFunc but do work with MarshalerTo #76725

@danvolchek

Description

@danvolchek

Go version

go version go1.25.4 X:nodwarf5 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/dan/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/dan/.config/go/env'
GOEXE=''
GOEXPERIMENT='nodwarf5'
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3030282131=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/dan/Desktop/Stuff/development/go-rw2/go.mod'
GOMODCACHE='/home/dan/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/dan/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/dan/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.25.4 X:nodwarf5'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

Ran this program: https://go.dev/play/p/Ha2umnCEcq8

What did you see happen?

a1: "custom marshaler for A"
b1: {}

What did you expect to see?

a1: "custom marshaler for A"
b1: "custom marshaler for B"

More specifically, both A1 and B1 embed another struct. Each of the embedded structs defines a custom marshaler: A by implementing the MarshalJSONTo interface and B by implementing a MarshalToFunc.

I expect both of these to be used, but the MarshalToFunc is not, I assume because B is embedded/inlined in B1.

I noticed that assigning a name to B so it doesn't get inlined (https://go.dev/play/p/OcY38RyE7dr) invokes the MarshalToFunc, but the result isn't inlined anymore so the output is different:

a1: "custom marshaler for A"
b1: {"b":"custom marshaler for B"}

If this is a known limitation, I don't see it documented at https://pkg.go.dev/encoding/json/v2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions