You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言JSON编码:如何用转义替代Unicode替换避免数据丢失?

Go语言实现JSON字符串转义而非替换的方法

当运行以下Go代码时:

package main

import (
   "encoding/json"
   "os"
)

func main() {
   json.NewEncoder(os.Stdout).Encode("\xa1") // 输出 "\ufffd"
}

会出现数据丢失问题——Go标准库的encoding/json编码器遇到无效UTF-8字节时,会自动替换成Unicode替换字符\ufffd,导致原始值无法恢复。而Python的json.dumps会将这类字节转义为\u00a1,解码后能完全还原原始内容:

import json

a = '\xa1'
b = json.dumps(a) # 输出 "\u00a1"
print(json.loads(b) == a) # 输出 True

Go标准库默认不支持这种转义行为,但可以通过自定义JSON序列化类型实现,核心是手动处理每个字节,将非ASCII或控制字符转义为\uXXXX格式而非替换。示例代码如下:

package main

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

// 自定义字符串类型,实现json.Marshaler接口
type RawString string

func (s RawString) MarshalJSON() ([]byte, error) {
	var buf bytes.Buffer
	buf.WriteByte('"')
	for _, b := range []byte(s) {
		switch {
		case b == '"' || b == '\\':
			// 转义引号和反斜杠
			buf.WriteByte('\\')
			buf.WriteByte(b)
		case b < 0x20:
			// 转义控制字符
			buf.WriteString(fmt.Sprintf("\\u%04x", b))
		case b >= 0x80:
			// 转义非ASCII字节为\u00XX格式
			buf.WriteString(fmt.Sprintf("\\u%04x", b))
		default:
			// 普通ASCII字符直接写入
			buf.WriteByte(b)
		}
	}
	buf.WriteByte('"')
	return buf.Bytes(), nil
}

func main() {
	// 使用自定义类型编码,输出 "\u00a1"
	json.NewEncoder(os.Stdout).Encode(RawString("\xa1"))

	// 验证解码后是否与原始值一致
	var decoded string
	encoded, _ := json.Marshal(RawString("\xa1"))
	json.Unmarshal(encoded, &decoded)
	fmt.Println(decoded == "\xa1") // 输出 true
}

说明:

  • 自定义RawString类型实现了json.Marshaler接口,手动控制JSON序列化流程;
  • 遍历字符串的每个字节,对需要转义的字符(引号、反斜杠、控制字符、非ASCII字节)统一处理为\uXXXX格式;
  • 生成的JSON字符串行为与Python的json.dumps一致,解码后可完全恢复原始数据。

内容的提问来源于stack exchange,提问作者user20619147

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:50:14