首頁 >後端開發 >Golang >分享一張Go json 踩坑紀錄

分享一張Go json 踩坑紀錄

藏色散人
藏色散人轉載
2021-06-15 11:05:232259瀏覽

下面由golang教學專欄給大家分享一個Go json 踩坑記錄,希望對需要的朋友有所幫助!

JSON,一種輕量級的資料交換語言,該語言以易於讓人閱讀的文字為基礎,用來傳送由屬性值或序列性的值所組成的資料物件。現已被廣泛應用,Go 當然也提供了完備的支持,透過 encoding/json 便可方便的序列化及反序列化 JSON 資料。但是也有些關鍵點需要額外注意。

Go 可使用json.Marshal() 便捷的獲取JSON 數據,查看該函數對應的godoc 文檔,裡面有這麼一段話:

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 3f1c4e4b6b16bbbd69b2ee476dc4f83a tags, the string is encoded using HTMLEscape, which replaces "0c43feb88fe3846c3aee3dd8022b72eb", "&", 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 編碼,會將“f36c3419fe208e1a01c47af887db73c5”, “&”, U 2028, 及U 2029 轉碼成“\u003c”,” \u003e”, “\u0026”, “\u2028”, 和“\u2029”。這在正常使用時是沒有問題的,但如果在對接第三方需要對 JSON 字串進行取摘要比對時,如果一方未進行 HTMLEscape 編碼,取出的摘要便會天差地別。上述文件中也給了解決方法,透過 SetEscapeHTML(false) 來停用便可。方法如下:

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

但是這樣使用仍然會有些問題,json.Encoder.Encode() 會在JSON 字串後面接著一個換行符,該函數原始碼如下:

// 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 字元。如果不需要該字符,則需要額外的將其剔除:

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

以上是分享一張Go json 踩坑紀錄的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除