如何阻止json.Marshal逃脱<和>?

时间:2015-02-18 23:04:06

标签: go

package main

import "fmt"
import "encoding/json"

type Track struct {
    XmlRequest string `json:"xmlRequest"`
}

func main() {
    message := new(Track)
    message.XmlRequest = "<car><mirror>XML</mirror></car>"
    fmt.Println("Before Marshal", message)
    messageJSON, _ := json.Marshal(message)
    fmt.Println("After marshal", string(messageJSON))
}

是否可以让json.Marshal无法逃避<>?我目前得到:

{"xmlRequest":"\u003ccar\u003e\u003cmirror\u003eXML\u003c/mirror\u003e\u003c/car\u003e"}

但我正在寻找类似的东西:

{"xmlRequest":"<car><mirror>XML</mirror></car>"}

5 个答案:

答案 0 :(得分:17)

从Go 1.7开始,你仍然无法使用json.Marshal()执行此操作。 source code for json.Marshal显示:

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

json.Marshal总是这样做的原因是:

  

字符串值编码为强制为有效UTF-8的JSON字符串,       用Unicode替换符号替换无效字节。       尖括号&#34;&lt;&#34;和&#34;&gt;&#34;被转移到&#34; \ u003c&#34;和&#34; \ u003e&#34;       防止某些浏览器误将JSON输出误解为HTML。       &符&#34;&amp;&#34;也逃到了#34; \#34; \#34;出于同样的原因。

这意味着您甚至无法通过编写自定义func (t *Track) MarshalJSON()来执行此操作,您必须使用不符合json.Marshaler界面的内容。

所以,解决方法是编写自己的函数:

func (t *Track) JSON() ([]byte, error) {
    buffer := &bytes.Buffer{}
    encoder := json.NewEncoder(buffer)
    encoder.SetEscapeHTML(false)
    err := encoder.Encode(t)
    return buffer.Bytes(), err
}

https://play.golang.org/p/FAH-XS-QMC

如果您想要任何结构的通用解决方案,您可以这样做:

func JSONMarshal(t interface{}) ([]byte, error) {
    buffer := &bytes.Buffer{}
    encoder := json.NewEncoder(buffer)
    encoder.SetEscapeHTML(false)
    err := encoder.Encode(t)
    return buffer.Bytes(), err
}

https://play.golang.org/p/bdqv3TUGr3

答案 1 :(得分:14)

在Go1.7中,https://play.golang.org/p/SJM3KLkYW-是一个新的选项来解决此问题:

  

编码/ JSON:   添加Encoder.DisableHTMLEscaping这提供了一种禁用&lt;,&gt;和&amp;的转义的方法。在JSON字符串中。

相关功能是

func (*Encoder) SetEscapeHTML

应该应用于编码器

enc := json.NewEncoder(os.Stdout)
enc.SetEscapeHTML(false)

简单示例:{{3}}

答案 2 :(得分:3)

解决此问题的另一种方法是,在json.RawMessage调用之后,将json.Marshal()中的那些转义字符替换为仅有效的UTF-8字符。

它对于<>以外的任何字母也适用。 (我曾经这样做是为了使非英语字母在JSON中易于阅读:D)

func _UnescapeUnicodeCharactersInJSON(_jsonRaw json.RawMessage) (json.RawMessage, error) {
    str, err := strconv.Unquote(strings.Replace(strconv.Quote(string(_jsonRaw)), `\\u`, `\u`, -1))
    if err != nil {
        return nil, err
    }
    return []byte(str), nil
}

func main() {
    // Both are valid JSON.
    var jsonRawEscaped json.RawMessage   // json raw with escaped unicode chars
    var jsonRawUnescaped json.RawMessage // json raw with unescaped unicode chars

    // '\u263a' == '☺'
    jsonRawEscaped = []byte(`{"HelloWorld": "\uC548\uB155, \uC138\uC0C1(\u4E16\u4E0A). \u263a"}`) // "\\u263a"
    jsonRawUnescaped, _ = _UnescapeUnicodeCharactersInJSON(jsonRawEscaped)                        // "☺"

    fmt.Println(string(jsonRawEscaped))   // {"HelloWorld": "\uC548\uB155, \uC138\uC0C1(\u4E16\u4E0A). \u263a"}
    fmt.Println(string(jsonRawUnescaped)) // {"HelloWorld": "안녕, 세상(世上). ☺"}
}

https://play.golang.org/p/pUsrzrrcDG-

我希望这对某人有帮助。

答案 3 :(得分:0)

不,你不能。

可能是第三方json包而不是std json lib。

更多细节:https://github.com/golang/go/issues/8592

答案 4 :(得分:0)

自定义功能不是最好的解决方案。

另一个图书馆如何解决这个问题。 我使用gabs

导入

go get "github.com/Jeffail/gabs"

使用

message := new(Track)
resultJson,_:=gabs.Consume(message)

fmt.Println(string(resultJson.EncodeJSON()))

我这样解决了这个问题。