golang——json的html标签转义问题

2019-04-14  本文已影响0人  yushu_bd

一、问题描述

json的Marshal 用来对slice,map,struct等结构化类型数据转义成[]byte/string,UnMarshal方法是用来对[]byte/string转义成指定结构的interface。但在处理html标签字符中,会存在转义问题。Marshal方法默认把html标签中的'<', '>' , '&'字符转义成unicode,为强制为有效UTF-8的JSON字符串,用Unicode替换符号替换无效字节。

go doc原文

String values encode as JSON strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune. The angle brackets “<” and “>” are escaped to “\u003c” and “\u003e” to keep some browsers from misinterpreting JSON output as HTML. Ampersand “&” is also escaped to “\u0026” for the same reason. This escaping can be disabled using an Encoder that had SetEscapeHTML(false) alled on it.
翻译:
字符串类型encode成json串时,会被强制转义成有效utf-8编码,同时会把utf-8无法识别的字符用uncode代替。尖括号“<”和“>”被转义为“\ u003c”和“\ u003e”,以防止某些浏览器将JSON输出误解为HTML。出于同样的原因,标签“&”也被转移到“\ u0026”。 可以使用在其上调用SetEscapeHTML(false)的编码器禁用此转义。

Marshal的源码

func Marshal(v interface{}) ([]byte, error) {
    e := newEncodeState()

    err := e.marshal(v, encOpts{escapeHTML: true}) 
    if err != nil {
        return nil, err
    }
    buf := append([]byte(nil), e.Bytes()...)

    e.Reset()
    encodeStatePool.Put(e)

    return buf, nil
}

这一行encOpts{escapeHTML: true}),这里的true导致标签被转义。

二、解决办法

针对上述问题,有两种解决办法,第一种是替换上述三个tag,第二种是SetEscapeHtml(false);

package test

import (
    "bytes"
    "encoding/json"
    "fmt"
    "strings"
)

type Html struct {
    Title  string
    Body   string
    Footer string
}

func ParseHtml() {
    htmlJson := Html{
        Title:  "<title>北京欢迎你</title>",
        Body:   "<body>北京是中国的首都,有600多年的建都历史</body>",
        Footer: "<script>js:pop('123')</script>",
    }

    strJson, err := json.Marshal(htmlJson)
    if err == nil {
        //原始的json串
        fmt.Println("原始json 串", string(strJson))
    }
    var content = string(strJson)
    //第一种方法,替换'<', '>', '&'
    content = strings.Replace(string(strJson), "\\u003c", "<", -1)
    content = strings.Replace(content, "\\u003e", ">", -1)
    content = strings.Replace(content, "\\u0026", "&", -1)
    fmt.Println("第一种解决办法:", content)

    //第二种方法,SetEscapeHTML(False)
    bf := bytes.NewBuffer([]byte{})
    jsonEncoder := json.NewEncoder(bf)
    jsonEncoder.SetEscapeHTML(false)
    jsonEncoder.Encode(htmlJson)
    fmt.Println("第二种解决办法:", bf.String())
}

输出:

原始json 串 {"Title":"\u003ctitle\u003e北京欢迎你\u003c/title\u003e","Body":"\u003cbody\u003e北京是中国的首都,有600多年的建都历史\u003c/body\u003e","Footer":"\u003cscript\u003ejs:pop('123')\u003c/script\u003e"}
第一种解决办法: {"Title":"<title>北京欢迎你</title>","Body":"<body>北京是中国的首都,有600多年的建都历史</body>","Footer":"<script>js:pop('123')</script>"}
第二种解决办法: {"Title":"<title>北京欢迎你</title>","Body":"<body>北京是中国的首都,有600多年的建都历史</body>","Footer":"<script>js:pop('123')</script>"}
上一篇下一篇

猜你喜欢

热点阅读