golang/beego response 中json.marshal字符转义问题解决

最近在做一个项目(使用的beego框架),其中的一个接口有返回FS(分布式文件系统)的一个文件地址URL,其中含有一个&符号,但是通过beego返回的response中发现将其转义为了

 “\u0026”,其原因是因为 beego 在对返回值进行 json.marshal 时会自动对特殊字符进行转义。

godoc文档,解释如下:

 

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) called on it.

也就是说json.marshal默认escapeHtml为true,会将<、>、&等字符转义。

其源码如下,可以看到encOpts{escapeHTML: true}是设置为了true

解决方案:在json.marshal时不去对特殊字符进行转义。

话不多说,直接上代码:

func (B *BaseController) FinishAndSendResponse() {
	if B.hasFinished {
		return
	}
	B.hasFinished = true
	if p := recover(); p != nil {
		B.Rsp.Code = consts.ErrorCodePanicOccur
		B.Rsp.Msg = "request when there was an panic"
		B.Rsp.Data = nil
		B.Log_Critical("A panic occurred during request: %v", p)
		B.Log_Error("Stack Info: \n %s", string(debug.Stack()))
	}
    
    //===将下面这段替换==start==
	s, err := json.Marshal(B.Rsp)
	if err != nil {
		B.Log_Error("marshal failed, error:%s", err.Error())
	} else {
		body := string(s)
		if len(body) < 10000 {
			B.Log_Info("response: %s", body)
		} else {
			B.Log_Debug("response: %s", body)
		}
	}
    //===将下面这段替换==end==

	B.Ctx.Output.Header("reqid", B.Rsp.Request_id)
	B.Ctx.Output.Body(s)
}



func (B *BaseController) FinishAndSendResponseNoSetEscapeHTML() {
	if B.hasFinished {
		return
	}
	B.hasFinished = true
	if p := recover(); p != nil {
		B.Rsp.Code = consts.ErrorCodePanicOccur
		B.Rsp.Msg = "request when there was an panic"
		B.Rsp.Data = nil
		B.Log_Critical("A panic occurred during request: %v", p)
		B.Log_Error("Stack Info: \n %s", string(debug.Stack()))
	}

    //===替换内容==start==
	bf := bytes.NewBuffer([]byte{})
	jsonEncoder := json.NewEncoder(bf)
	jsonEncoder.SetEscapeHTML(false)
	err := jsonEncoder.Encode(B.Rsp)
	if err != nil {
		B.Log_Error("marshal failed, error:%s", err.Error())
	} else {
		body := string(bf.Bytes())
		if len(body) < 10000 {
			B.Log_Info("response: %s", body)
		} else {
			B.Log_Debug("response: %s", body)
		}
	}
    //===替换内容==end==    

	B.Ctx.Output.Header("reqid", B.Rsp.Request_id)
	B.Ctx.Output.Body(bf.Bytes())
}

上述是我项目中的使用,下面给出一个实际的独立的例子:

package main

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

type ResponseData struct {
	Url string `json:"url"`
}

//序列化
func JsonMarshalNoSetEscapeHTML(data interface{}) ([]byte, error) {
	bf := bytes.NewBuffer([]byte{})
	jsonEncoder := json.NewEncoder(bf)
	jsonEncoder.SetEscapeHTML(false)
	if err := jsonEncoder.Encode(data); err != nil {
		return nil, err
	}

	return bf.Bytes(), nil
}

func main() {
	t := &ResponseData{
		Url: "http://10.255.1.123/fserver/hddown?fid=MC84Lzx8Oj5hbGwueGxzeF5eXnRhbmdoDEz$&u=0"",
	}
	res, err := JsonMarshalNoSetEscapeHTML(t)
	if err != nil {
		fmt.Println("JsonMarshalNoSetEscapeHTML failed.err:", err)
		return
	}
	fmt.Println("JsonMarshalNoSetEscapeHTML val:", string(res))
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值