我有一个结构,它包含作为[]字节字段的字符串,我想将其编码到JSON中。但是,生成的JSON包含切片内容的非预期字符串表示。以下是我所指的一个例子:
package main
import (
"fmt"
"encoding/json"
)
type Msg struct {
Content []byte
}
func main() {
helloStr := "Hello"
helloSlc := []byte(helloStr)
fmt.Println(helloStr, helloSlc)
obj := Msg{helloSlc}
json, _ := json.Marshal(obj)
fmt.Println(string(json))
}
这会产生以下输出:
Hello [72 101 108 108 111]
{"Content":"SGVsbG8="}
json是什么样的转换。对[]字节编码的字符串执行的Marshal()方法。如何使用字符串{"content":"Hello"}的原始内容生成JSON?
[]byte
被编组为base64编码的字符串。来自文件:
数组和切片值编码为JSON数组,除了
[]byte
编码为base64编码的字符串,nil切片编码为null JSON对象。
这些值在解组时会正确解码。
这样做的原因是JSON没有原始字节的本机表示。有关详细解释,请参阅此问题。
我遇到了同样的问题,即使这是一个相当古老的问题,并且已经回答了,还有另一个选择。
如果使用json.RawMessage
(内部是[]字节)作为类型而不是[]byte
,则编组将按预期工作到Json字符串中。
您可以使用第三方库来实现您想要的
package main
import (
"fmt"
"strconv"
"strings"
"time"
"unsafe"
jsoniter "github.com/json-iterator/go"
)
func main() {
err := test()
if err != nil {
panic(err)
}
}
func test() error {
jsoniter.RegisterTypeEncoder("[]uint8", &uint8Enc{})
var a struct {
A []byte `json:"a"`
B []byte `json:"b"`
}
a.A = []byte{'1', 1, 2, 3, '9'}
a.B = []byte(time.Now().String())
s, err := json.MarshalIndent(a, "", " ")
if err != nil {
return err
}
fmt.Println(string(s))
return nil
}
var json = jsoniter.ConfigCompatibleWithStandardLibrary
type uint8Enc struct{}
func (ue *uint8Enc) IsEmpty(ptr unsafe.Pointer) bool {
data := *((*[]uint8)(ptr))
return len(data) == 0
}
func (ue *uint8Enc) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
var (
data = *((*[]uint8)(ptr))
sb strings.Builder
)
const hexTable = "0123456789abcdef"
for _, v := range data {
if strconv.IsPrint(rune(v)) {
sb.WriteByte(v)
} else {
sb.WriteString(`x`)
sb.WriteByte(hexTable[v>>4])
sb.WriteByte(hexTable[v&0x0f])
}
}
stream.WriteString(sb.String())
}
结果如下
{
"a": "1\x01\x02\x039",
"b": "2023-06-05 09:15:38.551518 +0800 CST m=+0.003193401"
}