为什么在解组 JSON 时字符串和 []bytes 的处理方式不同?
Why are string and []bytes treated differently when unmarshaling JSON?
我阅读文档后的理解是 string
本质上是一个不可变的 []byte
并且可以在两者之间轻松转换。
然而,当从 JSON 解组时,这似乎不是真的。拿下面的例子程序来说:
package main
import (
"encoding/json"
"fmt"
)
type STHRaw struct {
Hash []byte `json:"hash"`
}
type STHString struct {
Hash string `json:"hash"`
}
func main() {
bytes := []byte(`{"hash": "nuyHN9wx4lZL2L3Ir3dhZpmggTQEIHEZcC3DUNCtQsk="}`)
stringHead := new(STHString)
if err := json.Unmarshal(bytes, &stringHead); err != nil {
return
}
rawHead := new(STHRaw)
if err := json.Unmarshal(bytes, &rawHead); err != nil {
return
}
fmt.Printf("String:\t\t%x\n", stringHead.Hash)
fmt.Printf("Raw:\t\t%x\n", rawHead.Hash)
fmt.Printf("Raw to string:\t%x\n", string(rawHead.Hash[:]))
}
这给出了以下输出:
String: 6e7579484e397778346c5a4c324c3349723364685a706d67675451454948455a63433344554e437451736b3d
Raw: 9eec8737dc31e2564bd8bdc8af77616699a0813404207119702dc350d0ad42c9
Raw to string: 9eec8737dc31e2564bd8bdc8af77616699a0813404207119702dc350d0ad42c9
相反,我希望每次都能收到相同的值。
有什么区别?
encoding/json 包的设计者决定应用程序必须在 string
值中提供有效的 UTF-8 文本,并且应用程序可以在 []byte
值中放置任意字节序列。包 base64 对 []byte
值进行编码以确保生成的字符串是有效的 UTF-8。
[]byte
值的编码在 Marshal function documentation 中描述。
这个决定并不是由 Go 语言的设计决定的。 string
类型可以包含任意字节序列。 []byte
类型可以包含有效的 UTF-8 文本。
设计者本可以在字段标签中使用标志来指示应该对 string
或 []byte
值进行编码以及使用哪个编码器,但他们并没有这样做。
我阅读文档后的理解是 string
本质上是一个不可变的 []byte
并且可以在两者之间轻松转换。
然而,当从 JSON 解组时,这似乎不是真的。拿下面的例子程序来说:
package main
import (
"encoding/json"
"fmt"
)
type STHRaw struct {
Hash []byte `json:"hash"`
}
type STHString struct {
Hash string `json:"hash"`
}
func main() {
bytes := []byte(`{"hash": "nuyHN9wx4lZL2L3Ir3dhZpmggTQEIHEZcC3DUNCtQsk="}`)
stringHead := new(STHString)
if err := json.Unmarshal(bytes, &stringHead); err != nil {
return
}
rawHead := new(STHRaw)
if err := json.Unmarshal(bytes, &rawHead); err != nil {
return
}
fmt.Printf("String:\t\t%x\n", stringHead.Hash)
fmt.Printf("Raw:\t\t%x\n", rawHead.Hash)
fmt.Printf("Raw to string:\t%x\n", string(rawHead.Hash[:]))
}
这给出了以下输出:
String: 6e7579484e397778346c5a4c324c3349723364685a706d67675451454948455a63433344554e437451736b3d
Raw: 9eec8737dc31e2564bd8bdc8af77616699a0813404207119702dc350d0ad42c9
Raw to string: 9eec8737dc31e2564bd8bdc8af77616699a0813404207119702dc350d0ad42c9
相反,我希望每次都能收到相同的值。
有什么区别?
encoding/json 包的设计者决定应用程序必须在 string
值中提供有效的 UTF-8 文本,并且应用程序可以在 []byte
值中放置任意字节序列。包 base64 对 []byte
值进行编码以确保生成的字符串是有效的 UTF-8。
[]byte
值的编码在 Marshal function documentation 中描述。
这个决定并不是由 Go 语言的设计决定的。 string
类型可以包含任意字节序列。 []byte
类型可以包含有效的 UTF-8 文本。
设计者本可以在字段标签中使用标志来指示应该对 string
或 []byte
值进行编码以及使用哪个编码器,但他们并没有这样做。