コンピュータ同士でデータをやり取りしたり、アプリの状態を保存したりする時、必ず出てくるのが「シリアライズ」と「デシリアライズ」です。
名前は少し難しく感じるかもしれませんが、やっていることはとてもシンプルです。
本記事では、具体例や図解、サンプルコードを使いながら、これら2つの違いと役割を初心者向けに丁寧に解説していきます。
シリアライズとデシリアライズとは
シリアライズの基本的なイメージ

シリアライズとは、プログラムの中で扱っている複雑なデータ(オブジェクトなど)を、通信や保存に適した1列のデータ(バイト列や文字列)に変換することです。
例えば、次のような情報があるとします。
- 名前: Taro
- 年齢: 20
- 点数: 90, 80, 70
このような情報は、プログラム内部では構造体やクラス、配列などの形で保持されています。
しかし、そのままの形では以下のようなことができません。
- ファイルにそのまま保存する
- ネットワーク経由で他のコンピュータへ送る
そこで、この複雑な形を「一直線に並べた形」に変換する必要があります。
この変換がシリアライズです。
デシリアライズの基本的なイメージ

デシリアライズとは、シリアライズされた1列のデータを、再びプログラム内で扱いやすい構造(オブジェクトや構造体など)に戻す処理です。
ファイルに保存されたデータや、ネットワークから送られてきたデータは、すべて「文字列」や「バイト列」の形になっています。
デシリアライズは、そのデータを読み取り、元の意味のある形に組み立てる作業だと考えると理解しやすくなります。
2つの違いを一言でまとめると
- シリアライズ
- オブジェクト → 1列のデータ(保存・送信用) に変換することです。
- デシリアライズ
- 1列のデータ → オブジェクト(プログラム内部で使う形) に戻すことです。
言い換えると、シリアライズは「書き出す」処理、デシリアライズは「読み込む」処理とも表現できます。
なぜシリアライズとデシリアライズが必要なのか
プログラム内部のデータはそのままでは扱いにくい
プログラム内のデータは、メモリ上に特殊な形式で保存されています。
これは、CPUが高速に処理できるように最適化されているため、人間が読める形ではありません。
このままでは、別のアプリケーションや別のコンピュータとデータを共有するのに不便です。
そのため、広く共通して使える形式(例: JSON、XML、バイナリ形式など)に変換する必要があります。
代表的な用途
シリアライズとデシリアライズは、さまざまな場面で利用されています。
主な用途を表にまとめます。
| 用途 | 説明 |
|---|---|
| ファイル保存 | アプリの設定やゲームのセーブデータをファイルに保存する時に、内部データをシリアライズします。 |
| ネットワーク通信 | API通信やオンラインゲームなどで、データを送受信する際にシリアライズ・デシリアライズします。 |
| キャッシュ | 一度計算した結果を保存し、あとで再利用するためにデータをシリアライズして保存します。 |
| メッセージキュー | 非同期処理のキューに渡すメッセージも、ほとんどがシリアライズされたデータです。 |
このように、「一度プログラムの外に出す」「別の場所へ渡す」場面では、ほぼ必ずシリアライズとデシリアライズが関わっています。
具体例で理解するシリアライズとデシリアライズ
ここでは、わかりやすさを重視して、JSONという形式を使った例を説明します。
JSON形式を使ったイメージ

たとえば、次のようなデータ構造を考えます。
- name: Taro
- age: 20
- scores: 90, 80, 70
これをJSONで表現すると、次のような文字列になります。
{"name": "Taro", "age": 20, "scores": [90, 80, 70]}
このとき、
- プログラム内部の構造体やクラス → JSON文字列 への変換がシリアライズ
- JSON文字列 → 構造体やクラス への変換がデシリアライズです。
C言語でのシンプルなシリアライズとデシリアライズ例
ここでは、あくまで「考え方」を理解するための簡単な例として、C言語でJSON風の文字列を扱うサンプルを示します。
実際の開発ではJSONライブラリを使うことが多いですが、ここでは手作業で「それらしいこと」を行います。
構造体をJSON風文字列にシリアライズする
#include <stdio.h>
#include <string.h>
// 学生の情報を表す構造体
typedef struct {
char name[32]; // 名前
int age; // 年齢
int score; // 点数
} Student;
// Student構造体をJSON風の文字列に変換(シリアライズ)する関数
void serialize_student(const Student *s, char *out, size_t out_size) {
// snprintfでJSON風の文字列を作成
// 実際のJSONライブラリでは、もっと厳密なエスケープなどを行います
snprintf(
out,
out_size,
"{\"name\":\"%s\",\"age\":%d,\"score\":%d}",
s->name,
s->age,
s->score
);
}
// JSON風の文字列からStudent構造体に変換(デシリアライズ)する関数
// ※非常に単純化した例であり、実運用には向きません
int deserialize_student(const char *json, Student *s) {
// JSON風文字列から値を抜き出すために、sscanfを使っています
// 実際にはJSONパーサーを使うべきです
char name[32];
int age;
int score;
int matched = sscanf(
json,
"{\"name\":\"%31[^\"]\",\"age\":%d,\"score\":%d}",
name,
&age,
&score
);
if (matched != 3) {
// 3つすべて読み取れなかった場合は失敗とみなす
return 0;
}
// 構造体に値をコピー
strcpy(s->name, name);
s->age = age;
s->score = score;
return 1;
}
int main(void) {
Student original = {"Taro", 20, 90}; // 元のオブジェクト
char buffer[128]; // シリアライズ先のバッファ
// シリアライズ(構造体 → JSON風文字列)
serialize_student(&original, buffer, sizeof(buffer));
printf("Serialized: %s\n", buffer);
// デシリアライズ(JSON風文字列 → 構造体)
Student restored;
if (deserialize_student(buffer, &restored)) {
printf("Deserialized: name=%s, age=%d, score=%d\n",
restored.name, restored.age, restored.score);
} else {
printf("Failed to deserialize.\n");
}
return 0;
}
Serialized: {"name":"Taro","age":20,"score":90}
Deserialized: name=Taro, age=20, score=90
このサンプルでは、次の2つの処理が対応しています。
- serialize_student関数
Student構造体をJSON風の文字列に変換しています。これはシリアライズです。
- deserialize_student関数
- JSON風の文字列から値を取り出し、
Student構造体に詰め直しています。これはデシリアライズです。
- JSON風の文字列から値を取り出し、
実際には、もっと複雑な構造や配列を扱いたくなるため、専用のライブラリを用いて行うのが一般的です。
しかし、「オブジェクトを文字列にする」「文字列からオブジェクトに戻す」という2段階の流れは常に同じです。
シリアライズ形式の代表例と違い
テキスト形式とバイナリ形式
シリアライズには、大きく分けて2種類のスタイルがあります。
| 種類 | 例 | 特徴 |
|---|---|---|
| テキスト形式 | JSON、XML、YAML など | 人間が読み書きしやすい。デバッグがしやすいが、データ量はやや多くなりがちです。 |
| バイナリ形式 | Protocol Buffers、MessagePack など | コンパクトかつ高速。人間が直接読むのは難しいが、通信や大量データに向いています。 |
初心者のうちはJSONのようなテキスト形式から理解するとイメージがつかみやすいです。
開発が進み、性能やサイズを重視したくなった段階で、バイナリ形式を検討すると良い流れになります。
JSONを使うメリット
JSONは、Web APIや設定ファイルで広く使われています。
メリットとしては次のような点が挙げられます。
- テキストなので人間が目で見て確認できる
- 多くのプログラミング言語で標準的にサポートされている
- ネットワーク通信との相性が良い
「まずはJSONでシリアライズ・デシリアライズを覚える」という学び方は、とても現実的でおすすめです。
シリアライズとデシリアライズを使う時の注意点
データの互換性
シリアライズしたデータは、「あとで同じ形式で読み戻すこと」を前提としています。
そのため、次のような変更には注意が必要です。
- 構造体やクラスのメンバーを削除・名前変更した
- フィールドの型を変更した(例: int → string など)
これらを無計画に行うと、過去に保存したデータが読み込めなくなる可能性があります。
実運用では、バージョン番号を持たせるなどして互換性を考えることが重要になります。
セキュリティ上の注意
特にデシリアライズには、セキュリティのリスクが潜んでいます。
- 信頼できない相手から送られてきたデータをそのままデシリアライズすると、予期しない動作を引き起こす可能性があります。
- 一部の言語やフレームワークのデシリアライズ機構には、過去に脆弱性が見つかった事例もあります。
基本的な考え方として、「外部から来たデータは必ず疑ってかかる」ことが大切です。
入力の検証や、必要以上に汎用的なデシリアライズ機能を使わない工夫が求められます。
まとめ
シリアライズとデシリアライズは、名前こそ難しそうですが、やっていることはとてもシンプルです。
シリアライズは「オブジェクトを1列のデータにすること」、デシリアライズは「1列のデータをオブジェクトに戻すこと」です。
この2つの処理によって、ファイル保存やネットワーク通信など、プログラムの外とのやり取りが可能になります。
まずはJSONのようなわかりやすい形式で、実際に試しながら感覚をつかむところから始めてみてください。
