在Go中将JSON []byte封送为字符串

watbbzwu  于 2023-06-07  发布在  Go
关注(0)|答案(3)|浏览(429)

我有一个包含字符串作为[]字节字段的结构体,我想将其编码为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()方法对[]byte编码的字符串执行哪种转换。我如何生成一个JSON与我的字符串的原始内容{“Content”:“Hello”}?

mnemlml8

mnemlml81#

[]byte被编组为base64编码的字符串。来自文档:
数组和切片值编码为JSON数组,除了[]byte编码为base64编码的字符串,nil切片编码为null JSON对象。
这些值在解组时被正确解码。
这样做的原因是JSON没有原始字节的原生表示。有关详细说明,请参见this question

1aaf6o9v

1aaf6o9v2#

我来了一个交叉同样的事情,即使这是一个相当古老的问题,并已回答有另一种选择。
如果你使用json.RawMessage(内部是一个[]字节)作为类型,而不是[]byte,那么Marshaling会像预期的那样转换为JSON String。

wko9yo5t

wko9yo5t3#

你可以使用第三方库来实现你想要的

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"
}

相关问题