📖 CLOB 的核心特点
-
存储内容:专门用于存储字符数据(如文章、日志、XML、JSON 等)。
-
容量大 :在 Oracle 中,CLOB 最多可存储 4GB 的文本数据,远超
VARCHAR2的 4000 字节限制。 -
字符集相关:CLOB 会依赖数据库的字符集(如 UTF-8、AL32UTF8),因此能正确存储多语言文本。
-
与 BLOB 的区别:
-
CLOB:存储字符数据,按字符流处理。
-
BLOB(Binary Large Object):存储二进制数据(如图片、音频、视频),按字节流处理。
-
➕ 使用场景
-
存储 大段文本:如新闻文章、技术文档、小说。
-
存储 结构化文本:如 JSON、XML 配置。
-
存储 日志与审计信息:需要保存完整的文本记录。
🔍 为什么会出现这种情况

Oracle CLOB 特性
-
CLOB 可能包含换行符、制表符、甚至不可见的分隔符。
-
在数据库中看似正常的 JSON,实际可能混入了
0x00、0x1c等控制字符。
Go 的 JSON 严格性
-
Go 的
encoding/json遵循 RFC 8259,对 控制字符(U+0000--U+001F) 要求必须转义。 -
如果字符串中直接存在这些字符,
json.Unmarshal会报错。
跨语言差异
-
Python 的
json.loads、JavaScript 的JSON.parse有时会自动忽略或宽松处理某些字符。 -
所以"在别的语言能解析,但 Go 不行"是常见现象。
🛠️ 如何定位问题
🔭Go 中对JSON 字符串做检查
Go
//📝 Powered by Moshow 郑锴 | 更多技术干货:https://zhengkai.blog.csdn.net/
for i, r := range jsonStr {
if r < 0x20 {
fmt.Printf("位置 %d 出现控制字符: U+%04X\n", i, r)
}
}
这样能打印出所有 不可见字符 的位置和 Unicode 编码。
或者用 %q 打印整个字符串:
Go
fmt.Printf("%q\n", jsonStr)
这样会把隐藏字符显示成 \u0000、\n 等形式。
🔭确认数据库存储
-
检查 Oracle CLOB 是否在写入时就混入了控制字符。
-
如果可能,使用
DBMS_LOB.SUBSTR或DUMP查看原始字节。
🔭调试输出
-
在 Go 中先
fmt.Println(len(jsonStr)),确认长度是否和预期一致。 -
如果长度异常,说明有隐藏字符。
✅ 解决方案
Show me the code : 清理异常格式
Go
package main
import (
"fmt"
"unicode/utf8"
)
// 📝 Powered by Moshow 郑锴 | 更多技术干货:https://zhengkai.blog.csdn.net/
// CleanJSONString 检测并清理 JSON 字符串中的非法控制字符
func CleanJSONString(s string) string {
var cleaned []rune
for i, r := range s {
// JSON 标准要求 U+0000 ~ U+001F 必须转义,否则非法
if r < 0x20 {
// 打印日志,方便定位问题
fmt.Printf("发现非法字符: 位置=%d, Unicode=U+%04X\n", i, r)
// 跳过该字符,不加入结果
continue
}
// 保留合法字符
cleaned = append(cleaned, r)
}
return string(cleaned)
}
func main() {
// 模拟从 Oracle CLOB 取出的 JSON,里面混入了非法字符 \u0000
raw := `{"name":"test\u0000data","age":30}`
fmt.Println("原始字符串长度:", utf8.RuneCountInString(raw))
fmt.Println("原始字符串:", raw)
cleaned := CleanJSONString(raw)
fmt.Println("清理后字符串长度:", utf8.RuneCountInString(cleaned))
fmt.Println("清理后字符串:", cleaned)
}
➕运行结果
bash
原始字符串长度: 29
原始字符串: {"name":"test\u0000data","age":30}
发现非法字符: 位置=17, Unicode=U+0000
清理后字符串长度: 28
清理后字符串: {"name":"testdata","age":30}
📌 总结
-
问题根源:CLOB 中混入了 Go JSON 不接受的控制字符。
-
定位方法 :逐字节扫描或
%q打印,找出非法字符。 -
解决方案 :在
json.Unmarshal前清理掉这些字符,或在数据库层面保证写入的 JSON 纯净。