>  기사  >  백엔드 개발  >  Go json 트랩 레코드 공유

Go json 트랩 레코드 공유

藏色散人
藏色散人앞으로
2021-06-15 11:05:232223검색

다음은 golang튜토리얼 칼럼에서 공유한 Go json 함정 기록입니다. 필요한 친구들에게 도움이 되길 바랍니다!

Go는 json.Marshal()을 사용하여 JSON 데이터를 쉽게 얻을 수 있습니다. 이 함수에 해당하는 godoc 문서를 보면 다음 구절이 있습니다: 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()])
json.Marshal() code> 직렬화 시 HTMLEscape 인코딩이 수행되며 "6745434bf92a2979d589ede8e8e7bea9", "&", U+2028, U+2029가 "u003c", "u003e", "u0026으로 트랜스코딩됩니다. ”, “u2028”, “u2029”. 이는 일반적인 사용에서는 문제가 되지 않지만, 제3자가 JSON 문자열을 추출하고 비교해야 하는 경우, 한쪽이 HTMLEscape 인코딩을 수행하지 않으면 추출된 추출이 완전히 달라집니다. 위 문서에서는 <code>SetEscapeHTML(false)로 비활성화할 수 있는 솔루션도 제공합니다. 방법은 다음과 같습니다. 🎜rrreee🎜그러나 이 방법을 사용하면 여전히 몇 가지 문제가 있습니다. json.Encoder.Encode()는 JSON 문자열 뒤에 🎜줄 바꿈 문자🎜를 추가합니다. 이 함수의 코드는 다음과 같습니다: 🎜rrreee🎜알겠습니다. 함수가 직렬화 후에 또 다른 n 문자를 쓰는 것을 볼 수 있습니다. 문자가 필요하지 않은 경우 추가 제거가 필요합니다. 🎜rrreee

위 내용은 Go json 트랩 레코드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제