你正在使用哪个版本的Go( go version
)?
$ go version
go version go1.20 linux/amd64
这个问题在最新版本中是否会重现?
是的。
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/lukeshu/.cache/go-build"
GOENV="/home/lukeshu/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/lukeshu/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/lukeshu/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/run/user/1000/tmpdir/go-build2160073961=/tmp/go-build -gno-record-gcc-switches"
你做了什么?
我传递了一个用 "
引号包裹的二进制垃圾到 json.Valid
。
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonStr := "\"0\x85\xcd\xc0\xf3\xcb\xc1\xb3\xf2\xf5\xa4\xc1\xd40\xba\xe9\""
fmt.Println(json.Valid([]byte(jsonStr)))
}
https://go.dev/play/p/rrtmrEL3Ipd
你期望看到什么?
由于JSON被指定为“Unicode代码点的序列”(ECMA-404)或“以UTF-8、UTF-16或UTF-32编码”(RFC 7159),我期望包含无法解释为Unicode代码点的字节的JSON文档不被认为是有效的。
你实际上看到了什么?
它认为文档是有效的,尽管它包含了无法解释为Unicode代码点的字节。
4条答案
按热度按时间zyfwsgd61#
@LukeShu 请注意,json.Unmarshal文档中提到了这一点:
在解析带引号的字符串时,无效的UTF-8或无效的UTF-16代理对不会被视为错误。相反,它们会被替换为Unicode替换字符U+FFFD。
由于json.Unmarshal和json.Valid共享底层代码,您的示例看起来符合预期行为。
也许可以改进一下文档?
k4ymrczo2#
我理解
Unmarshal
和Valid
共享底层代码,但Unmarshal
对无效输入持宽松态度并不意味着Valid
应该将其识别为有效(至少在文档中没有自己的备注时不应该)。我发现这种不一致是因为各种函数之间的不一致性,我原本以为即使它们有怪癖,由于共享底层实现,它们至少会保持一致。我发现
json.Unmarshal(any)
→json.MarshalIndent()
会将二进制垃圾转换为 U+FFFD,而json.Indent()
和json.Compact()
会原样通过。我认为对无效 JSON 的不同行为是合理的,但后来惊讶地发现json.Valid()
将它识别为有效。(尽管这种不同的行为令人惊讶,但我真的不能说这是一个bug;而json.Valid()
将它识别为有效对我来说是一个明显的bug。)ej83mcc03#
CC @dsnet@mvdan
7lrncoxx4#
遗憾的是,
json
包允许无效的UTF-8,因为RFC 8259第8.1节明确指出JSON必须是UTF-8。鉴于我们已经口头承诺在
Unmarshal
中处理无效的UTF-8,我们还应该记录Valid
中它的操作方式。