Golang中如何避免JSON解码器移除字符串中的反斜杠字符
Golang中如何避免JSON解码器移除字符串中的反斜杠字符 我有一个如下所示的JSON字符串:
{“toDb”:“BEGIN let rs1 resultset := (\u0002); let rs2 resultset := select c2 from t1 where RLIKE(c1,‘\d+’); END;“}
当我将这个JSON字符串解码到一个结构体中时,它会移除转义字符。这不是我期望的结果。那么,我该如何避免这种行为呢?以下是示例代码链接:Go Playground - The Go Programming Language
更多关于Golang中如何避免JSON解码器移除字符串中的反斜杠字符的实战教程也可以访问 https://www.itying.com/category-94-b0.html
听起来真正的修复必须应用于JSON的源头……
使用 RawMessage 感觉像是针对错误输入的一种变通方法,而非真正的修复……
更多关于Golang中如何避免JSON解码器移除字符串中的反斜杠字符的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我通过使用 map[string]json.RawMessage 作为解码的结构体找到了解决方案。感谢您的回复。
我没有看到任何内容被移除。
反序列化后的数据中,转义字符得到了正确的表示。
如果你想表示字符串 \u0002 或 \\d,而不是字节 0x02 或字符串 \d,你需要在 JSON 中添加额外的转义。即 \\u0002 和 \\\\d。
在Go中,JSON解码器会自动处理转义字符,这是符合JSON规范的行为。要保留原始字符串中的反斜杠,你需要使用json.RawMessage或自定义解码逻辑。以下是解决方案:
方案1:使用json.RawMessage保留原始JSON
package main
import (
"encoding/json"
"fmt"
)
type MyStruct struct {
ToDb json.RawMessage `json:"toDb"`
}
func main() {
jsonStr := `{"toDb":"BEGIN let rs1 resultset := (\\u0002); let rs2 resultset := select c2 from t1 where RLIKE(c1,'\\d+'); END;"}`
var data MyStruct
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
panic(err)
}
// 直接使用原始JSON数据
fmt.Printf("原始JSON字段: %s\n", string(data.ToDb))
// 如果需要获取字符串值(仍会处理转义)
var toDbStr string
if err := json.Unmarshal(data.ToDb, &toDbStr); err != nil {
panic(err)
}
fmt.Printf("解码后的字符串: %s\n", toDbStr)
}
方案2:自定义JSON解码
package main
import (
"encoding/json"
"fmt"
"strings"
)
type CustomString string
func (cs *CustomString) UnmarshalJSON(data []byte) error {
// 去除JSON字符串两端的引号
if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' {
// 保留原始内容,不进行转义处理
*cs = CustomString(data[1 : len(data)-1])
return nil
}
// 如果不是字符串类型,按默认方式处理
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
*cs = CustomString(s)
return nil
}
type MyStruct struct {
ToDb CustomString `json:"toDb"`
}
func main() {
jsonStr := `{"toDb":"BEGIN let rs1 resultset := (\\u0002); let rs2 resultset := select c2 from t1 where RLIKE(c1,'\\d+'); END;"}`
var data MyStruct
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
panic(err)
}
fmt.Printf("保留反斜杠的字符串: %s\n", data.ToDb)
fmt.Printf("包含原始转义字符: %q\n", string(data.ToDb))
}
方案3:使用原始字符串处理
package main
import (
"encoding/json"
"fmt"
)
type MyStruct struct {
ToDb string `json:"toDb"`
}
func main() {
// 注意:在Go字符串字面量中,反斜杠需要转义
jsonStr := `{"toDb":"BEGIN let rs1 resultset := (\\u0002); let rs2 resultset := select c2 from t1 where RLIKE(c1,'\\d+'); END;"}`
var data MyStruct
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
panic(err)
}
// 重新编码以查看实际存储的内容
output, _ := json.Marshal(data)
fmt.Printf("重新编码的JSON: %s\n", output)
fmt.Printf("存储的字符串值: %s\n", data.ToDb)
}
关键点说明:
-
JSON规范要求:JSON解码器必须处理转义序列,
\u0002会被解码为Unicode字符,\d中的反斜杠会被移除。 -
字符串字面量转义:在Go代码中定义JSON字符串时,反斜杠需要双重转义:
\\u0002→ JSON中的\u0002\\d+→ JSON中的\d+
-
验证JSON有效性:
func validateJSON(jsonStr string) {
var raw map[string]interface{}
if err := json.Unmarshal([]byte(jsonStr), &raw); err != nil {
fmt.Printf("JSON无效: %v\n", err)
} else {
fmt.Println("JSON有效")
}
}
选择哪种方案取决于你的具体需求:如果需要完全保留原始JSON格式,使用json.RawMessage;如果需要自定义处理逻辑,实现自定义的UnmarshalJSON方法。

