分享一个Go json 踩坑记录


本文摘自php中文网,作者藏色散人,侵删。

下面由golang教程栏目给大家分享一个Go json 踩坑记录,希望对需要的朋友有所帮助!

JSON,一种轻量级的资料交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。现已经被广泛应用,Go 当然也提供了完备的支持,通过 encoding/json 便可方便的序列化及反序列化 JSON 数据。但是也有些关键点需要额外注意下。

Go 可使用 json.Marshal() 便捷的获取 JSON 数据,查看该函数对应的 godoc 文档,里面有这么一段话:

1

String values encode as JSON strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune. So that the JSON will be safe to embed inside HTML <script> tags, the string is encoded using HTMLEscape, which replaces "<", ">", "&", U+2028, and U+2029 are escaped to "\u003c","\u003e", "\u0026", "\u2028", and "\u2029". This replacement can be disabled when using an Encoder, by calling SetEscapeHTML(false).

json.Marshal() 在进行序列化时,会进行 HTMLEscape 编码,会将 “<”, “>”, “&”, U+2028, 及 U+2029 转码成 “\u003c”,”\u003e”, “\u0026”, “\u2028”, 和 “\u2029”。这在正常使用时是没有问题的,但如果在对接第三方需要对 JSON 字符串进行取摘要比对时,如果一方未进行 HTMLEscape 编码,取出的摘要便会天差地别。上述文档中也给出了解决方法,通过 SetEscapeHTML(false) 来禁用便可。方法如下:

1

bf := bytes.NewBuffer([]byte{})jsonEncoder := json.NewEncoder(bf)jsonEncoder.SetEscapeHTML(false)_ = jsonEncoder.Encode(body)jsonStr := bf.String()

但是这样使用仍然会有些问题,json.Encoder.Encode() 会在 JSON 字符串后接一个 换行符,该函数源码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

// Encode writes the JSON encoding of v to the stream,

// followed by a newline character.

//

// See the documentation for Marshal for details about the

// conversion of Go values to JSON.

func (enc *Encoder) Encode(v interface{}) error {

    if enc.err != nil {

        return enc.err

    }

    e := newEncodeState()

    err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML})

    if err != nil {

        return err

    }

 

    // Terminate each value with a newline.

    // This makes the output look a little nicer

    // when debugging, and some kind of space

    // is required if the encoded value was a number,

    // so that the reader knows there aren't more

    // digits coming.

    e.WriteByte('\n')

 

    b := e.Bytes()

    if enc.indentPrefix != "" || enc.indentValue != "" {

        if enc.indentBuf == nil {

            enc.indentBuf = new(bytes.Buffer)

        }

        enc.indentBuf.Reset()

        err = Indent(enc.indentBuf, b, enc.indentPrefix, enc.indentValue)

        if err != nil {

            return err

        }

        b = enc.indentBuf.Bytes()

    }

    if _, err = enc.w.Write(b); err != nil {

        enc.err = err

    }

    encodeStatePool.Put(e)

    return err

}

可以看出,该函数在进行序列化后又写入了一个 \n 字符。如果不需要该字符,则需要额外的将其剔除:

1

jsonStr := string(bf.Bytes()[:bf.bf.Len()])

以上就是分享一个Go json 踩坑记录的详细内容,更多文章请关注木庄网络博客!!

相关阅读 >>

游戏服务器框架Gonet

关于Golang 指针理解

Golang内存分配逃逸分析

Golang反射为什么慢

聊聊promtail的positions

聊聊Golang的zap的sink

Golang返回错误时如何正确处理

Golang mysql操作介绍

beeGo项目和Go项目 打包部署到linux

Golang channel有什么好处

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...