はじめに 「JSON圧縮」は“意味は変えずに、できるだけ短くする”こと
ここでいう「JSON圧縮」は、
GZipなどのバイナリ圧縮ではなく、
「余計な改行・インデント・スペースを削って、JSON文字列を最小限の長さにする」
いわゆる JSONの“ミニファイ(minify)” の話です。
APIレスポンスを少しでも軽くしたい
ログやファイルに保存するサイズを減らしたい
「整形済みJSON」を、送信用にコンパクトに戻したい
といった場面で、JSON圧縮ユーティリティは地味に役に立ちます。
ポイントは、
- JSONの「意味」は一切変えない
- 変えるのは「見た目(空白・改行)」だけ
ということです。
基本方針:一度パースしてから「インデントなし」で書き出す
なぜ「改行削除」だけではダメなのか
初心者がやりがちなのは、
- 改行を全部消す
- タブやスペースを全部消す
といった「文字列置換ベース」の圧縮です。
これは危険です。
文字列の中に含まれるスペースや改行(例: "Hello World")
JSONの構造上必要なスペース(例: "key": "value" のコロン後のスペース)
など、「消していい空白」と「消してはいけない空白」を区別できないからです。
正しいやり方は、整形のときと同じで、
- JSON文字列を一度パースして“構造”として理解する
- インデントなし・余計な空白なしでシリアライズし直す
という二段構えです。
実務で使える基本実装(System.Text.Json版)
完成形のユーティリティ
using System;
using System.Text.Json;
public static class JsonCompressUtil
{
public static string CompressJson(string? json)
{
if (string.IsNullOrWhiteSpace(json))
{
return string.Empty;
}
try
{
using var doc = JsonDocument.Parse(json);
var options = new JsonSerializerOptions
{
WriteIndented = false
};
string compressed = JsonSerializer.Serialize(doc.RootElement, options);
return compressed;
}
catch (JsonException)
{
return json;
}
}
}
C#この1メソッドで、「JSON圧縮ユーティリティ」としてほぼ実務投入できます。
何をしているか、順番にかみ砕いていきます。
重要ポイント1:JsonDocument.Parse で“構造として”読み直す
using var doc = JsonDocument.Parse(json);
C#ここでやっているのは、
- JSON文字列をパースして
- メモリ上の「JSONドキュメント」として扱えるようにする
という処理です。
これにより、
- 改行やインデントがどうなっていようが関係なく
- JSONの「キー」「値」「配列」「オブジェクト」などの構造だけを取り出せる
状態になります。
もしここで JsonException が出たら、その文字列は「JSONとして不正」です。
今回のユーティリティでは、
catch (JsonException)
{
return json;
}
C#として、「圧縮はあきらめて元の文字列を返す」方針にしています。
重要ポイント2:WriteIndented = false で“最小限のJSON”にする
var options = new JsonSerializerOptions
{
WriteIndented = false
};
string compressed = JsonSerializer.Serialize(doc.RootElement, options);
C#JsonSerializer.Serialize は、
オブジェクトをJSON文字列に変換するメソッドです。
WriteIndented = false(デフォルト)を指定すると、
- 改行なし
- インデントなし
- 必要最小限のスペースだけ
という「コンパクトなJSON」が出力されます。
つまり、
- パース →
JsonDocument - インデントなしでシリアライズ → 圧縮済みJSON文字列
という流れで、「意味はそのまま、見た目だけ最小化」しているわけです。
動作例で違いを確認する
整形済みJSONを圧縮する
string pretty = @"{
""id"": 1,
""name"": ""Taro"",
""tags"": [
""dev"",
""backend""
],
""active"": true
}";
string compressed = JsonCompressUtil.CompressJson(pretty);
Console.WriteLine(compressed);
C#出力イメージは次のようになります。
{"id":1,"name":"Taro","tags":["dev","backend"],"active":true}
中身(キーや値、配列の要素)は一切変わっていませんが、
改行とインデントが消え、1行に詰まっています。
もともと1行JSONを渡した場合
string raw = "{\"id\":1,\"name\":\"Taro\"}";
string compressed = JsonCompressUtil.CompressJson(raw);
Console.WriteLine(compressed); // {"id":1,"name":"Taro"}
C#この場合は、ほぼそのまま返ってきます。
「整形済みでも、1行でも、とりあえず“正規化されたコンパクトJSON”にする」
というイメージです。
不正JSONへの扱いをどうするか
「壊れていても、とりあえず見たい」か、「絶対に弾きたい」か
JsonDocument.Parse は厳密なので、
途中で切れているJSONや、余計な文字が混ざったJSONに対しては JsonException を投げます。
今回の実装では、
- 正しいJSON → 圧縮して返す
- 不正なJSON → 元の文字列をそのまま返す
という挙動にしています。
理由は、
- ログやデバッグ用途では、「壊れていても中身を見たい」ことが多い
- 圧縮ユーティリティが例外でアプリ全体を落とすのは避けたい
からです。
一方で、「外部からの入力を厳密に検証したい」ような場面では、
ここで例外をそのまま投げる実装に変えるのもアリです。
Newtonsoft.Json(Json.NET)版も押さえておく
既存プロジェクトでよく使われるパターン
Json.NETを使う場合も、考え方は同じです。
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public static class JsonCompressUtilNewtonsoft
{
public static string CompressJson(string? json)
{
if (string.IsNullOrWhiteSpace(json))
{
return string.Empty;
}
try
{
var token = JToken.Parse(json);
return token.ToString(Formatting.None);
}
catch (JsonReaderException)
{
return json;
}
}
}
C#JToken.Parse でパースし、ToString(Formatting.None) で「インデントなしJSON」を出力しています。
新規開発なら System.Text.Json を優先、
既存コードがJson.NETベースならこちら、という使い分けです。
業務ユーティリティとしてのまとめ方
「整形」と「圧縮」をセットで持っておくと強い
前に作った「JSON整形」と今回の「JSON圧縮」は、
ペアで持っておくとかなり便利です。
public static class JsonPretty
{
public static string Format(string? json)
=> JsonFormatUtil.FormatJson(json);
}
public static class JsonMini
{
public static string Compress(string? json)
=> JsonCompressUtil.CompressJson(json);
}
C#これで、
- デバッグ時 →
JsonPretty.Format(responseBody) - 送信前・保存前 →
JsonMini.Compress(json)
というように、用途に応じて簡単に切り替えられます。
nullや空文字の扱いをユーティリティ側で決めておく
今回の実装では、
- null / 空 / 空白だけ → 空文字を返す
- 不正JSON → 元の文字列を返す
というルールにしています。
これにより、呼び出し側は、
- いちいちnullチェックを書かなくてよい
- 例外処理を毎回書かなくてよい
というメリットがあります。
プロジェクトのポリシーに合わせて、
- 不正JSONは例外
- nullはそのままnull
などに変えるのもOKですが、
「ユーティリティ側で統一ルールを決める」のが大事です。
まとめ 「JSON圧縮ユーティリティ」は“通信や保存を少しだけ賢くする、小さな最適化”
JSON圧縮(ミニファイ)は、
見た目を犠牲にしてでも、サイズを少しでも減らしたいときに使うテクニックです。
押さえておきたいポイントは、
JSON圧縮は“改行削除”ではなく、“パースしてからインデントなしでシリアライズし直す”こと。System.Text.Json なら JsonDocument.Parse + JsonSerializer.Serialize(WriteIndented = false) で簡潔に書けること。
不正JSONへの扱い(例外にするか、元の文字列を返すか)をユーティリティ側で決めておくと、呼び出し側が楽になること。
「整形」と「圧縮」をセットで持っておくと、デバッグと本番の両方で使い分けやすいこと。
ここまで理解できれば、「なんとなく1行にしている」段階から一歩進んで、
“構造を意識した、安全で実務的なJSON圧縮ユーティリティ”を、
自分のC#コードの中に自然に組み込めるようになっていきます。
