英文:
How to stop json.Marshal from escaping < and >?
问题
package main
import "fmt"
import "encoding/json"
type Track struct {
XmlRequest string json:"xmlRequest"
}
func main() {
message := new(Track)
message.XmlRequest = "
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>"}
英文:
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))
}
Is it possible to make json.Marshal
not escape <
and >
? I currently get:
{"xmlRequest":"\u003ccar\u003e\u003cmirror\u003eXML\u003c/mirror\u003e\u003c/car\u003e"}
but I am looking for something like this:
{"xmlRequest":"<car><mirror>XML</mirror></car>"}
答案1
得分: 78
截至Go 1.7版本,你仍然**无法使用json.Marshal()**来实现这个功能。json.Marshal的源代码显示:
> err := e.marshal(v, encOpts{escapeHTML: true})
json.Marshal总是这样做的原因是:
字符串值被编码为强制转换为有效UTF-8的JSON字符串,将无效字节替换为Unicode替换符。角括号“<”和“>”被转义为“\u003c”和“\u003e”,以防止某些浏览器将JSON输出错误地解释为HTML。与此相同的原因,和号“&”也被转义为“\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
}
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
英文:
As of Go 1.7, you still cannot do this with json.Marshal(). The source code for json.Marshal shows:
> err := e.marshal(v, encOpts{escapeHTML: true})
The reason json.Marshal always does this is:
> 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 means you cannot even do it by writing a custom func (t *Track) MarshalJSON()
, you have to use something that does not satisfy the json.Marshaler interface.
So, the workaround, is to write your own function:
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
If you want a generic solution for any struct, you could do:
func JSONMarshal(t interface{}) ([]byte, error) {
buffer := &bytes.Buffer{}
encoder := json.NewEncoder(buffer)
encoder.SetEscapeHTML(false)
err := encoder.Encode(t)
return buffer.Bytes(), err
}
答案2
得分: 36
在Go1.7中,添加了一个新选项来解决这个问题:
> encoding/json:
> 添加了Encoder.DisableHTMLEscaping。这提供了一种在JSON字符串中禁用<、>和&转义的方法。
相关的函数是
func (*Encoder) SetEscapeHTML
应该应用于Encoder。
enc := json.NewEncoder(os.Stdout)
enc.SetEscapeHTML(false)
简单示例:https://play.golang.org/p/SJM3KLkYW-
英文:
In Go1.7 the have added a new option to fix this:
> encoding/json:
> add Encoder.DisableHTMLEscaping This provides a way to disable the escaping of <, >, and & in JSON strings.
The relevant function is
func (*Encoder) SetEscapeHTML
That should be applied to a Encoder.
enc := json.NewEncoder(os.Stdout)
enc.SetEscapeHTML(false)
Simple example: https://play.golang.org/p/SJM3KLkYW-
答案3
得分: 8
这不是直接回答问题,但如果你想知道如何处理json.Marshal
转义的<
和>
,这可能是一个答案...
解决这个问题的另一种方法是在json.Marshal()
调用之后,将json.RawMessage
中的转义字符替换为有效的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() {
// 两者都是有效的JSON。
var jsonRawEscaped json.RawMessage // 带有转义Unicode字符的原始JSON
var jsonRawUnescaped json.RawMessage // 不带转义Unicode字符的原始JSON
// '\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": "안녕, 세상(世上). ☺"}
}
希望对某人有所帮助。
英文:
This doesn't answer the question directly but it could be an answer if you're looking for a way how to deal with json.Marshal
escaping <
and >
...
Another way to solve the problem is to replace those escaped characters in json.RawMessage
into just valid UTF-8 characters, after the json.Marshal()
call.
It will work as well for any letters other than <
and >
. (I used to do this to make non-English letters to be human readable in 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-
I hope this helps someone.
答案4
得分: 6
这是我的解决方法:
// Marshal是一个UTF-8友好的编组器。Go的json.Marshal不是UTF-8友好的,因为它将有效的UTF-8和JSON字符"&"、"<"、">"替换为"slash u" unicode转义形式(例如\u0026)。它预先转义以适应HTML友好性。在文本中可能包含任何这些字符的情况下,不应使用json.Marshal。Go Playground中破坏标题的示例: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
}
英文:
Here's my workaround:
// 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
}
答案5
得分: 1
不,你不能。
第三方的json包可能是一个选择,而不是标准的json库。
更多详情请参考:https://github.com/golang/go/issues/8592
英文:
No, you can't.
A third-party json package might be the choice rather than the std json lib.
More detail:https://github.com/golang/go/issues/8592
答案6
得分: 1
我有一个要求,需要将XML存储在JSON中。起初,我在通过JSON传递后解组XML时遇到了很大的困难,但实际上问题是因为我尝试将XML字符串解组为json.RawMessage导致的。实际上,我需要将其解组为字符串,然后将其强制转换为[]byte以供xml.Unmarshal使用。
type xmlInJson struct {
Data string `json:"data"`
}
var response xmlInJson
err := json.Unmarshal(xmlJsonData, &response)
var xmlData someOtherStructThatMatchesTheXmlFormat
err = xml.Unmarshal([]byte(response.Data), &xmlData)
英文:
I had a requirement to store xml inside json :puke:
At first I was having significant difficulty unmarshalling that xml after passing it via json, but my issue was actually due to trying to unmarshall the xml string as a json.RawMessage. I actually needed to unmarshall it as a string and then coerce it into []byte for the xml.Unmarshal.
type xmlInJson struct {
Data string `json:"data"`
}
var response xmlInJson
err := json.Unmarshall(xmlJsonData, &response)
var xmlData someOtherStructThatMatchesTheXmlFormat
err = xml.Unmarshall([]byte(response.Data), &xmlData)
答案7
得分: -2
自定义函数并不是最好的解决方案。
那么使用另一个库来解决如何呢?我使用了gabs
库。
导入:
go get "github.com/Jeffail/gabs"
使用:
message := new(Track)
resultJson,_:=gabs.Consume(message)
fmt.Println(string(resultJson.EncodeJSON()))
我是这样解决这个问题的。
英文:
Custom function is not kind of the best solution.
How about another library to solve this.
I use gabs
import
go get "github.com/Jeffail/gabs"
use
message := new(Track)
resultJson,_:=gabs.Consume(message)
fmt.Println(string(resultJson.EncodeJSON()))
I solve that problem like this.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论