Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > golang json 特殊字符转义

golang中json转换的特殊字符转义问题

作者:Moshow郑锴

Go语言中使用encoding/json进行序列化时,默认会对<、>、&等特殊字符进行转义,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

在日常的 Go 开发中,encoding/json 包是最常用的 JSON 序列化与反序列化工具。然而,很多开发者在使用过程中会遇到一个“隐蔽的坑”:特殊字符被自动转义。这不仅可能导致前后端数据不一致,还可能在 API 返回结果中引发解析异常。

本文将深入分析 Go 中 JSON 转义的机制、常见问题场景,并给出实用的解决方案。

1. 问题复现

来看一个简单的例子:

package main

import (
    "encoding/json"
    "fmt"
)

type Data struct {
    Link string `json:"link"`
}

func main() {
    data := Data{Link: "https://zhengkai.blog.csdn.net/?a=1&b=2"}
    b, _ := json.Marshal(data)
    fmt.Println(string(b))
}

输出结果为:

{"link":"https://zhengkai.blog.csdn.net/?a=1\u0026b=2"}

可以看到,& 被转义成了 \u0026。如果客户端严格依赖原始 URL,这种转义会导致 请求参数丢失或解析失败

2. 转义的原因

Go 的 encoding/json 默认会对 HTML 特殊字符进行转义,目的是 防止 XSS 攻击。例如:

这种设计在 Web 安全层面是合理的,但在 API 返回 JSON 时,往往会带来兼容性问题。

3. 可能导致的异常

4. 解决方案

✅ 方法一:关闭 HTML 转义

使用 json.Encoder 并调用 SetEscapeHTML(false)

encoder := json.NewEncoder(os.Stdout)
encoder.SetEscapeHTML(false)
_ = encoder.Encode(data)

输出结果为:

{"link":"https://zhengkai.blog.csdn.net/?a=1&b=2"}

✅ 方法二:自定义序列化函数

func MarshalNoEscape(v interface{}) ([]byte, error) {
    var buf bytes.Buffer
    enc := json.NewEncoder(&buf)
    enc.SetEscapeHTML(false)
    err := enc.Encode(v)
    return buf.Bytes(), err
}

这样可以在项目中统一调用,避免重复配置。

5. 最佳实践

6.为什么是可逆过程?

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
    original := map[string]string{
        "html": "<div>Hello & World</div>",
        "sql": "SELECT * FROM users WHERE age > 18",
    }
    
    fmt.Println("=== 原始数据 ===")
    fmt.Printf("html: %s\n", original["html"])
    fmt.Printf("sql: %s\n", original["sql"])
    
    // 第一次 Marshal(默认转义)
    jsonData1, _ := json.Marshal(original)
    fmt.Println("\n=== 第一次 Marshal 后的 JSON ===")
    fmt.Println(string(jsonData1))
    
    // 保存为字符串
    savedString := string(jsonData1)
    fmt.Println("\n=== 保存的字符串 ===")
    fmt.Println(savedString)
    
    // 从字符串再次解析为 JSON
    var parsedData map[string]string
    err := json.Unmarshal([]byte(savedString), &parsedData)
    if err != nil {
        fmt.Printf("解析错误: %v\n", err)
    } else {
        fmt.Println("\n=== 解析后的数据 ===")
        fmt.Printf("html: %s\n", parsedData["html"])
        fmt.Printf("sql: %s\n", parsedData["sql"])
    }
    
    // 验证数据是否一致
    fmt.Println("\n=== 数据一致性验证 ===")
    fmt.Printf("html 字段是否一致: %t\n", original["html"] == parsedData["html"])
    fmt.Printf("sql 字段是否一致: %t\n", original["sql"] == parsedData["sql"])
}
=== 原始数据 ===
html: <div>Hello & World</div>
sql: SELECT * FROM users WHERE age > 18
=== 第一次 Marshal 后的 JSON ===
{"html":"\u003cdiv\u003eHello \u0026 World\u003c/div\u003e","sql":"SELECT * FROM users WHERE age \u003e 18"}
=== 保存的字符串 ===
{"html":"\u003cdiv\u003eHello \u0026 World\u003c/div\u003e","sql":"SELECT * FROM users WHERE age \u003e 18"}
=== 解析后的数据 ===
html: <div>Hello & World</div>
sql: SELECT * FROM users WHERE age > 18
=== 数据一致性验证 ===
html 字段是否一致: true
sql 字段是否一致: true

7.跨语言转换要注意的点⚠️

7.1 数值精度问题

7.2字符编码差异

7.3特殊字符转义

结语

Go 的 JSON 转义机制体现了语言对安全的重视,但在实际业务中,开发者需要根据场景灵活调整。通过 SetEscapeHTML(false) 或自定义函数,我们可以在 安全性与兼容性之间找到平衡

到此这篇关于golang中json转换的特殊字符转义问题的文章就介绍到这了,更多相关golang json 特殊字符转义内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文