什么是 JSON 字符串转义?
JSON 字符串转义是将字符串内的特殊字符转换为转义序列的过程,使 JSON 解析器能够正确读取而不破坏结构。JSON 规范(ECMA-404 / RFC 8259)要求字符串值中的某些字符前必须加反斜杠。如果不进行正确转义,字符串内的原始双引号或换行符会提前终止字符串,导致解析错误。
每个 JSON 字符串都以双引号作为界定符。当字符串本身包含双引号、反斜杠或控制字符(U+0000 至 U+001F)时,该字符必须替换为对应的转义序列。例如,原始换行符变为 \n,制表符变为 \t,双引号变为 \"。任何 Unicode 码位也可表示为 \uXXXX 形式,其中 XXXX 为四位十六进制值。
反转义(反向操作)将这些反斜杠序列还原为原始字符。当收到的 JSON 载荷中字符串值被双重转义时,或需要从 JSON 日志条目中提取原始文本以在界面或终端显示时,可使用此功能。日志聚合管道中经常遇到此问题:当 JSON 编码的消息作为字符串值存储在另一个 JSON 文档内时,内层字符串中的每个反斜杠都会出现两次。
为什么使用 JSON 转义工具?
手动添加或删除反斜杠既繁琐又容易出错,尤其是处理多行文本、文件路径或嵌入的代码片段时。专用转义工具能捕获手动编辑容易遗漏的边界情况。
JSON 字符串转义使用场景
JSON 转义序列参考
JSON 规范定义了两个强制转义(双引号和反斜杠)以及六个常用控制字符的短转义序列。所有其他控制字符(U+0000 至 U+001F)必须使用 \uXXXX 形式。U+FFFF 以上的字符(如 emoji)可表示为 UTF-16 代理对:\uD83D\uDE00。
| 字符 | 描述 | 转义形式 |
|---|---|---|
| " | Double quote | \" |
| \ | Backslash | \\ |
| / | Forward slash | \/ (optional) |
| \n | Newline (LF) | \n |
| \r | Carriage return | \r |
| \t | Tab | \t |
| \b | Backspace | \b |
| \f | Form feed | \f |
| U+0000–U+001F | Control characters | \u0000–\u001F |
| U+0080+ | Non-ASCII (e.g. emoji) | \uXXXX or raw UTF-8 |
JSON 转义 vs. JSON 编码
开发者有时会混淆字符串转义与完整 JSON 文档编码的概念。
代码示例
主流语言均内置了相应功能。以下是 JavaScript、Python、Go 和 jq 的示例:
// JSON.stringify escapes a value and wraps it in quotes
JSON.stringify('Line 1\nLine 2') // → '"Line 1\\nLine 2"'
// To get just the inner escaped string (no surrounding quotes):
const escaped = JSON.stringify('She said "hello"').slice(1, -1)
// → 'She said \\"hello\\"'
// Parsing reverses the escaping
JSON.parse('"tabs\\tand\\nnewlines"') // → 'tabs\tand\nnewlines'
// Handling Unicode: emoji in JSON
JSON.stringify('Price: 5\u20ac') // → '"Price: 5\u20ac"' (raw euro sign)import json
# json.dumps escapes and quotes a string
json.dumps('Line 1\nLine 2') # → '"Line 1\\nLine 2"'
# Ensure ASCII: replace non-ASCII with \uXXXX sequences
json.dumps('Caf\u00e9', ensure_ascii=True) # → '"Caf\\u00e9"'
# Keep UTF-8 characters as-is (default in Python 3)
json.dumps('Caf\u00e9', ensure_ascii=False) # → '"Caf\u00e9"'
# Unescape by round-tripping through json.loads
json.loads('"She said \\"hello\\""') # → 'She said "hello"'package main
import (
"encoding/json"
"fmt"
)
func main() {
// json.Marshal escapes a Go string for JSON
raw := "Line 1\nLine 2\tindented"
b, _ := json.Marshal(raw)
fmt.Println(string(b))
// → "Line 1\nLine 2\tindented"
// Unescape with json.Unmarshal
var out string
json.Unmarshal([]byte(`"She said \"hello\""`), &out)
fmt.Println(out)
// → She said "hello"
}# Escape a raw string into a JSON-safe value echo 'Line 1 Line 2 with tab' | jq -Rs '.' # → "Line 1\nLine 2\twith tab\n" # Unescape a JSON string back to raw text echo '"She said \"hello\""' | jq -r '.' # → She said "hello"