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: wrong encoding for json.Number field with string option (struct tag) #34268

Closed
breml opened this issue Sep 12, 2019 · 3 comments
Closed
Labels
Milestone

Comments

@breml
Copy link
Contributor

@breml breml commented Sep 12, 2019

If the string option is set on a struct field of type json.Number, the value gets encoded without quotes. If this encoded value is then unmarshaled back, it fails, because the expected quotes are missing.

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

$ go version
go version go1.12.5 linux/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/lubr/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/lubr/go"
GOPROXY=""
GORACE=""
GOROOT="/home/lubr/.gvm/versions/go1.12.5.linux.amd64"
GOTMPDIR=""
GOTOOLDIR="/home/lubr/.gvm/versions/go1.12.5.linux.amd64/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
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-build368255501=/tmp/go-build -gno-record-gcc-switches"

What did you do?

package main

import (
	"encoding/json"
	"fmt"
	"log"
)

type stringTest struct {
	JSONNumberStringOption json.Number `json:",string"`
}

func main() {
	b, err := json.Marshal(stringTest{
		JSONNumberStringOption: "2",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(b))

	var res stringTest
	err = json.Unmarshal(b, &res)
	if err != nil {
		log.Fatal(err)
	}
}

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

What did you expect to see?

{"JSONNumberStringOption":"2"}

What did you see instead?

{"JSONNumberStringOption":2}
2019/09/12 21:33:02 json: invalid use of ,string struct tag, trying to unmarshal unquoted value into json.Number
exit status 1
breml added a commit to breml/go that referenced this issue Sep 12, 2019
Add quotes if a value of type json.Number with the string option
(struct tag) set is marshaled. This ensures, that the resulting json
can be unmarshaled into the source struct without error.

Fixes golang#34268
@gopherbot

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Sep 12, 2019

Change https://golang.org/cl/195043 mentions this issue: encoding/json: fix marshal for json.Number ,string

@mvdan

This comment has been minimized.

Copy link
Member

@mvdan mvdan commented Sep 13, 2019

The fact that you can encode but then not decode back seems to point clearly at a bug here; thanks for spotting this.

@mvdan mvdan added the NeedsFix label Sep 13, 2019
@mvdan mvdan added this to the Go1.14 milestone Sep 13, 2019
@mdempsky

This comment has been minimized.

Copy link
Member

@mdempsky mdempsky commented Sep 13, 2019

I added and then quickly deleted this comment, but I think a few people still saw it via email notifications, so I figured I might as well restore it for posterity:

Package json's documentation describes:

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.

So using it for json.Number is technically against the documentation.

I don't have any preference here; but if json.Number is updated to support the "string" option, then this documentation should also be updated.

I made this comment before realizing that Number is a declared type whose underlying type is string. After realizing that, however, I didn't feel confident about my interpretation and wanted to retract it, rather than add uninformed drive-by chatter. (But you can't delete anything from the Internet.)

@gopherbot gopherbot closed this in 49e7c76 Sep 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.