美文网首页
golang——json的html标签转义问题

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

作者: yushu_bd | 来源:发表于2019-04-14 13:40 被阅读0次

    一、问题描述

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

    相关文章

      网友评论

          本文标题:golang——json的html标签转义问题

          本文链接:https://www.haomeiwen.com/subject/bbdfdqtx.html