JSON を Base64 にエンコードする方法
- 入力 · テキスト に JSON を貼り付けるか、サンプル を押して例のオブジェクトを読み込みます。
- 出力 · Base64 から Base64 をコピーします。サイズの数値で、どれだけ長くなったかがわかります。
- URL、Cookie、トークンのような値にするなら、URLセーフ(- _) と パディングなし(=) にチェックを入れます。
- ダウンロード で結果を
base64.txtとして保存します。
このページのサンプル {"id":42,"name":"base64hub","tags":["json","encode"],"active":true} は 67 バイトで、eyJpZCI6NDIsIm5hbWUiOiJiYXNlNjRodWIiLCJ0YWdzIjpbImpzb24iLCJlbmNvZGUiXSwiYWN0aXZlIjp0cnVlfQ== にエンコードされます。結果を確かめるには 入れ替え を押すか、整形表示もできる Base64 を JSON に変換 を使ってください。
空白や書式で Base64 は変わる
Base64 は JSON テキストの文字をそのままエンコードするので、同じ意味の 2 つの文書でも、空白が 1 つ違えば Base64 も変わります。
| JSON テキスト | Base64 |
|---|---|
{"a":1} | eyJhIjoxfQ== |
{"a": 1} | eyJhIjogMX0= |
{ "a": 1 } | eyAiYSI6IDEgfQ== |
{"a":1} を 3 行に整形したもの | ewogICJhIjogMQp9 |
Base64 を比較、キャッシュ、署名する場合は、1 つのシリアライザーと固定の設定で JSON を生成し、その文字列そのものをエンコードしてください。キーの順序も落とし穴です。ほとんどのシリアライザーは挿入順を保つので、{"a":1,"b":2} と {"b":2,"a":1} は違う結果になります。
Python と JavaScript はデフォルトでは一致しない
オブジェクト {"name": "Zoë", "n": 1} を、各言語のデフォルトでシリアライズした場合:
| シリアライザー | JSON テキスト | Base64 |
|---|---|---|
JavaScript の JSON.stringify | {"name":"Zoë","n":1} | eyJuYW1lIjoiWm/DqyIsIm4iOjF9 |
Python の json.dumps | {"name": "Zo\u00eb", "n": 1} | eyJuYW1lIjogIlpvXHUwMGViIiwgIm4iOiAxfQ== |
Python で separators=(",", ":")、ensure_ascii=False を指定 | {"name":"Zoë","n":1} | eyJuYW1lIjoiWm/DqyIsIm4iOjF9 |
URLセーフとパディングなしにチェックを入れると、JavaScript 版は eyJuYW1lIjoiWm_DqyIsIm4iOjF9 になります。
Base64 の JSON が使われる場面
- HTTP ヘッダー。 トレースやユーザーのメタデータなどのコンテキストを運ぶカスタムヘッダーには、Base64 の JSON がよく入っています。ヘッダーの値に JSON の引用符や非 ASCII 文字をそのまま入れるのは安全でないからです。多くのサーバーは約 8 KB を超えるヘッダー行を拒否するので、ペイロードは小さく保ってください。
- URL パラメーター。 OAuth の
stateの値、リダイレクト先、共有リンクには、小さな JSON オブジェクトが Base64URL で入っていることがあります。 - 環境変数とシークレット。 CI システムに入れるサービスアカウントの鍵など、JSON の設定全体をエスケープなしで 1 つの変数に収められます。
- トークン形式。 JWT のヘッダーとペイロードは、パディングなしの Base64URL でエンコードした JSON です。署名付きのトークンを作るには JWT エンコーダー を使ってください。このページはエンコードするだけです。
Base64 はサイズを 3 分の 1 増やし、JSON 自体の引用符やキーが値より大きいこともよくあります。先に圧縮すると得になるのはどんなときかは、Base64 のサイズ増加 で解説しています。
コードで JSON を Base64 に変換する
const obj = { name: "Zoë", n: 1 };
const bytes = new TextEncoder().encode(JSON.stringify(obj));
btoa(String.fromCharCode(...bytes)); // "eyJuYW1lIjoiWm/DqyIsIm4iOjF9"
Buffer.from(JSON.stringify(obj)).toString("base64url"); // "eyJuYW1lIjoiWm_DqyIsIm4iOjF9" (Node.js)
TextEncoder の手順を省いて btoa(JSON.stringify(obj)) とすると、ë が Latin-1 の 1 バイトとしてエンコードされ(eyJuYW1lIjoiWm/rIiwibiI6MX0=)、UTF-8 のデコーダーでは読めなくなります。絵文字など Latin-1 の範囲外の文字があると例外が発生します。
import base64, json
obj = {"name": "Zoë", "n": 1}
text = json.dumps(obj, separators=(",", ":"), ensure_ascii=False)
base64.b64encode(text.encode("utf-8")).decode() # 'eyJuYW1lIjoiWm/DqyIsIm4iOjF9'
ほかのオプションは JavaScript、Node.js、Python のページにあります。
よくある質問
JSON を Base64 に変換するには?
JSON を文字列にシリアライズし、その文字列を UTF-8 としてエンコードしてから、バイト列を Base64 エンコードします。上に JSON を貼り付ければ結果が得られます。コードでは、JavaScript なら UTF-8 の変換を挟んで btoa を、Python なら base64.b64encode(json.dumps(obj).encode()) を使います。
同じオブジェクトなのに Python と JavaScript で Base64 が違うのはなぜですか?
シリアライザーが違うからです。Python の json.dumps は : と , の後に空白を入れ、非 ASCII 文字を \u00eb のようにエスケープしますが、JSON.stringify はどちらもしません。合わせるには separators=(",", ":") と ensure_ascii=False を使ってください。
このツールは JSON を検証したり minify したりしますか?
しません。空白も含め、入力したテキストをそのままエンコードします。出力を短くしたい場合や、ほかのシステムの出力とバイト単位で一致させたい場合は、先に JSON を minify してください。
URL に入れる JSON には URLセーフな Base64 を使うべきですか?
使うべきです。標準の Base64 には URL で意味を持つ +、/、= が含まれることがあります。URLセーフとパディングなしにチェックを入れてください。JWT と同じ形式になります。