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

Car*_*cía 20 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))
}
Run Code Online (Sandbox Code Playgroud)

是否有可能做出json.Marshal无法逃脱<>?我目前得到:

{"xmlRequest":"\u003ccar\u003e\u003cmirror\u003eXML\u003c/mirror\u003e\u003c/car\u003e"}
Run Code Online (Sandbox Code Playgroud)

但我正在寻找这样的事情:

{"xmlRequest":"<car><mirror>XML</mirror></car>"}
Run Code Online (Sandbox Code Playgroud)

dav*_*ave 24

从Go 1.7开始,你仍然不能用json.Marshal()来做到这一点.json.Marshal源代码显示:

> err := e.marshal(v, encOpts{escapeHTML: true})
Run Code Online (Sandbox Code Playgroud)

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

字符串值编码为强制为有效UTF-8的JSON字符串,用Unicode替换符号替换无效字节.尖括号"<"和">"被转义为"\ u003c"和"\ u003e",以防止某些浏览器将JSON输出误解为HTML.出于同样的原因,Ampersand"&"也被转移到"\ u0026".

这意味着您甚至无法通过编写自定义来执行此操作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
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

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

  • 最后一个惊喜(尽管有据可查)是Encode()在末尾添加了换行符(\ n)。因此,要完成此标准化方法,您可以考虑使用string.TrimRight(t,“ \ n”)。 (2认同)
  • 等效的修剪新行:`b = bytes.TrimRight(buffer.Bytes(), "\n")` (2认同)

adr*_*lzt 17

在Go1.7中,添加了一个新选项来修复此问题:

encoding/json:add Encoder.DisableHTMLEscaping这提供了一种禁用JSON字符串中<,>和&的转义的方法.

相关功能是

func (*Encoder) SetEscapeHTML
Run Code Online (Sandbox Code Playgroud)

那应该应用于编码器.

enc := json.NewEncoder(os.Stdout)
enc.SetEscapeHTML(false)
Run Code Online (Sandbox Code Playgroud)

简单的例子:https://play.golang.org/p/SJM3KLkYW-

  • 这是不等价的,因为 json.Encode 以新行结束。马歇尔没有。 (2认同)

Zam*_*col 7

这是我的解决方法:

// Marshal is a UTF-8 friendly marshaler.  Go's json.Marshal is not UTF-8
// friendly because it replaces the valid UTF-8 and JSON characters "&". "<",
// ">" with the "slash u" unicode escaped forms (e.g. \u0026).  It preemptively
// escapes for HTML friendliness.  Where text may include any of these
// characters, json.Marshal should not be used. Playground of Go breaking a
// title: https://play.golang.org/p/o2hiX0c62oN
func Marshal(i interface{}) ([]byte, error) {
    buffer := &bytes.Buffer{}
    encoder := json.NewEncoder(buffer)
    encoder.SetEscapeHTML(false)
    err := encoder.Encode(i)
    return bytes.TrimRight(buffer.Bytes(), "\n"), err
}

Run Code Online (Sandbox Code Playgroud)


Coc*_*nut 6

这不能直接回答问题,但如果您正在寻找一种如何处理json.Marshal转义<>...的方法,它可能是一个答案。

解决问题的另一种方法是json.RawMessagejson.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": "??, ??(??). ?"}
}
Run Code Online (Sandbox Code Playgroud)

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

我希望这可以帮助别人。