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: marshal of custom type not quoted when using ",string" tag field #20651

Open
aronatkins opened this Issue Jun 12, 2017 · 4 comments

Comments

Projects
None yet
5 participants
@aronatkins

aronatkins commented Jun 12, 2017

Please answer these questions before submitting your issue. Thanks!

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

go version go1.8.3 linux/amd64

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

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/var/lib/jenkins/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-build418778517=/tmp/go-build"
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"

What did you do?

We receive JSON which encodes booleans as numeric strings. Parsing that JSON works just fine with a ",string" tag and a type with its own UnmarshalJSON definition. The quoting is removed and we get the proper boolean value.

Quoting is not added when serializing this type, which means that JSON IN>decode>encode>OUT produces OUT different than IN.

type parsedBool bool

func (basi *parsedBool) UnmarshalJSON(data []byte) error {
	v, err := strconv.ParseBool(string(data))
	if err != nil {
		return err
	}
	*basi = parsedBool(v)
	return nil
}

func (basi parsedBool) MarshalJSON() ([]byte, error) {
	if basi {
		return []byte(`1`), nil
	} else {
		return []byte(`0`), nil
	}
}

https://play.golang.org/p/ccIw4E6UJF

What did you expect to see?

Equivalent support for ",string" for this custom type when both encoding and decoding. I was surprised by the difference in behavior. Both cases should either err (because parsedBool is not bool) or properly handle the quotes.

The json docs state:

The "string" option signals that a field is stored as JSON inside a JSON-encoded string. It applies only to fields of string, floating point, integer, or boolean types.

What did you see instead?

Given:

	wrapped := struct {
		P parsedBool `json:",string"`
		B bool       `json:",string"`
	}{
		P: true,
		B: true,
	}

This is marshaled as:

{"P":1,"B":"true"}

This was unexpected because we properly parse:

{"P":"1","B":"true"}
@OneOfOne

This comment has been minimized.

Contributor

OneOfOne commented Jun 13, 2017

You are using a custom marshal function, not sure why is that unexpected?

@mvdan

This comment has been minimized.

Member

mvdan commented Jun 13, 2017

Perhaps the package docs should be improved to clarify that ,string gets ignored when using a Marshaler/Unmarshaler.

@aronatkins

This comment has been minimized.

aronatkins commented Jun 13, 2017

@OneOfOne + @mvdan The primary concern is the inconsistency between reading/writing JSON. Note that the quoting is removed when parsing JSON but not added when creating JSON.

The inconsistency can be addressed either by supporting quoting when serializing ",string"-annotated custom types (which are still primitives under the hood) OR by removing support for quote-removal when deserializing ",string"-annotated custom types.

Both options have backwards-compatibility issues, as programs are likely to have already worked around the observed behavior.

@andybons

This comment has been minimized.

Member

andybons commented Apr 11, 2018

Marking for Go2 due to backwards-incompatible changes that would need to be made.

@andybons andybons added the Go2 label Apr 11, 2018

@andybons andybons added this to the Go2 milestone Apr 11, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment