JSON 字串化工具
您輸入的內容不會被儲存、記錄或分享。
將 JSON 轉換成可直接貼進程式碼的跳脫字串,或把跳脫字串還原成易讀的 JSON。
使用方式
- 選擇「字串化」進行跳脫,或選擇「還原」反向轉換。
- 將 JSON 貼到輸入框。
- 使用複製按鈕複製結果。
跳脫實際上做了什麼
字串化會先解析你的 JSON 並壓縮,再把結果包在雙引號中,並跳脫所有會讓字串提早結束的字元。內部的雙引號變成 \",反斜線加倍成 \\,低於 U+0020 的控制字元則變成簡寫 \n、\r、\t、\b 和 \f,沒有簡寫的則寫成 \u00XX。
有兩樣東西刻意不處理。斜線不會跳脫,因為 JSON 並不要求;你有時會在其他工具的輸出中看到 \/,這是合法但不必要的寫法,源自在 HTML 中隱藏 </script> 字串的老習慣。非 ASCII 字元也保留原樣,不會轉成 \u 跳脫序列,所以帶重音的文字、中文等 CJK 字元與表情符號都能維持可讀。兩種寫法對解析器來說意義相同,而可讀的那種更容易比對差異。
雙重編碼,以及它為何惱人
這個工具之所以存在,是因為跳脫不具冪等性,而人們通常是在除錯別的問題時才發現這一點。把文件跳脫一次,引號會變成 \";把結果再跳脫一次,就會變成 \\\",因為剛加上的反斜線本身也成了需要跳脫的字元。每跳脫一次,反斜線大約就會加倍。
這是資料被序列化兩次的特徵:應該存放物件的欄位裡放的卻是一串 JSON 字串,讀日誌時可以明顯看到引號前面帶著反斜線。當程式碼對某個框架已經序列化過的值再呼叫一次序列化器,就會發生這種情況;解法幾乎總是移除兩次呼叫中的一次,而不是再加一道解碼步驟。
反字串化就是用來拆解它的工具。每一層編碼執行一次,觀察反斜線每次減半。當反斜線消失、結果能解析成物件時,你就知道總共有幾層了。
什麼時候需要跳脫後的字串
把資料嵌入另一份 JSON 文件時,Webhook 封包、工作佇列與稽核日誌通常就是這樣承載任意內容的。把環境變數設成 JSON 值時,否則 Shell 會吃掉引號。把請求內容貼進 CI 工作的 YAML 檔案時。在原始碼中以字面值撰寫測試資料時。把文件存放在文字欄位而非原生 JSON 欄位時。
在這些情況下,內層的引號都必須穿過一層原本會把它們當作結束符號的解析,而跳脫正是讓它們完整通過的方法。
逐字看懂跳脫規則
JSON 明確定義了哪些字元不能直接出現在字串裡。雙引號會讓字串提早結束,所以要寫成 \"。反斜線是跳脫序列的開頭,所以要加倍寫成 \\。所有低於 U+0020 的控制字元都被禁止,其中五個有簡短寫法:換行是 \n、歸位是 \r、定位是 \t、退格是 \b、換頁是 \f。這個範圍內的其他字元則要寫成像 \u0000 這樣的六字元跳脫序列。
有兩個字元常常被跳脫,但其實並非必要。正斜線可以寫成 \/,這是合法的,只是沒有必要;這個習慣來自把 JSON 嵌進 HTML 的情境,否則 </script> 這串字會讓 script 元素提早結束。非 ASCII 字元也可以寫成 \u 跳脫序列,有些函式庫預設就這麼做,好讓輸出維持純 ASCII。
這個工具兩者都原樣保留,因為可讀的輸出比較好做差異比對,而且每個剖析器對這兩種形式的處理完全相同。如果下游系統真的需要純 ASCII 的輸出,那是序列化器上的一個選項,而不是文件本身的要求。
讓 JSON 安全地穿過 shell
shell 是跳脫最常出錯的地方,因為同時有兩層引號在作用。bash 的單引號會把裡面的東西原封不動傳過去,這就是為什麼 curl -d '{"name":"value"}' 可以運作,而同一串字換成雙引號就不行——shell 會先展開變數、去掉某些字元,curl 根本看不到原本的內容。
當內容本身含有單引號時,單引號的寫法也會壞掉,比較穩健的作法是乾脆別把它塞進命令列:把主體寫進檔案,改用 curl -d @body.json,或是用管線餵進去。對於程式產生的內容,jq -n 比字串串接更安全,因為它從結構上就保證產生合法的 JSON。
存放 JSON 的環境變數是相關的情況,在 CI 設定和 Docker 裡特別常見。那個值通常得同時撐過 YAML 的引號處理、shell 的展開,以及應用程式自己的剖析,總共三層。要保持理智的辦法是把 JSON 先用 base64 編碼後再傳遞,到使用的地方才解碼。
結構化日誌與重複編碼的指紋
日誌管線愈來愈期待每行一個 JSON 物件,這讓欄位可以直接搜尋,而不必對自由文字下正規表示式。陷阱在於記錄一個已經序列化過的物件:該欄位會以 JSON 字串而不是巢狀物件的形式抵達,日誌系統只會把它當成一整塊不透明的內容來建索引。
看得見的徵兆正是這個工具要還原的那種指紋——某個值讀起來是 {\"id\":42} 而不是 {"id":42}。每多一層,反斜線大致就會翻倍,所以數一數就知道被編碼了幾次。
該修的地方在產生端。把物件交給 logger,讓它只序列化一次,而不是自己先序列化再傳一個字串進去。如果字串來自別處且無法更動,多數日誌平台都有 JSON 剖析過濾器,可以在寫入時把該欄位拆開,這比在每一次查詢時處理要好得多。
把一份內容嵌進另一份文件
Webhook 的封裝、工作佇列和稽核日誌都面對同一個問題:一個有自己欄位的外層,必須攜帶任意的內層內容。把內層序列化成字串是最簡單的答案,代價是內層文件變得不透明——沒有再剖析一次,就無法查詢、驗證或建索引。
另一種作法是把內層維持成巢狀物件,這樣仍然可以查詢,但外層的 schema 必須允許任意結構,而且在任何走訪文件的程式眼中,兩個命名空間會混在一起。多數系統最後是按用途分別決定:需要檢視內容時用巢狀,只是轉送時就字串化。
當內容很大或是二進位資料時,還有值得記住的第三個選項:把它放在別的地方,只送出一個參照。在封裝裡放一個 URL 加上校驗碼,既避開跳脫問題也避開大小限制,而且大型檔案的流程最後大多本來就是這樣做的。
不靠工具讀懂跳脫過的文字
對短字串來說,用眼睛還原編碼是可行的,也值得練習,因為這會讓你看懂發生了什麼事。只有一層時,鍵和值的周圍會出現 \"。兩層時會看到 \\\",而且整個字串通常被本身也被跳脫過的引號包住。再往上,反斜線就會比內容還多,這時候用數的比用讀的快。
一個好用的檢查點是字串的開頭。正確巢狀的物件會以沒有被跳脫的大括號開始;被編碼兩次的則會以一個引號接著一個被跳脫的大括號開始,這個形狀看久了會一眼認出來。
在終端機裡,printf '%s\n' "$value" 可以解開一層,jq -r '.' 再解開一層,依序套用並看著反斜線每次減半,就是這裡的 unstringify 按鈕在命令列上的等價作法。
常見問題
- 字串化實際上做了什麼?
- 它會先驗證並壓縮您的 JSON,接著用引號包住整段內容,並跳脫其中的引號與控制字元,產生可直接嵌入原始碼的字串字面值。
- 什麼時候需要跳脫過的 JSON 字串?
- 最常見的是把 JSON 嵌入另一份 JSON、shell 指令、環境變數或測試資料時。若不跳脫,內部的引號會提前結束字串。
- 為什麼還原時顯示輸入不是引號字串?
- 還原功能預期輸入是字串字面值,也就是整段內容都被雙引號包住。如果貼上的是一般物件,請改用「字串化」。
- 我的資料會上傳到伺服器嗎?
- 不會。跳脫處理完全在您的瀏覽器中以 JavaScript 執行,資料不會離開您的裝置。
最後更新:
請提供操作步驟、預期結果及實際結果。請移除機密與個人資料。
