C#でJSONを扱う!DataContractJsonSerializerの使い方を徹底解説
生徒
「C#を使って、インターネットでよく見るJSONという形式のデータを扱いたいのですが、どうすればいいですか?」
先生
「JSONですね。C#には標準でDataContractJsonSerializerという、データをJSONに変換したり、元に戻したりする仕組みがありますよ。」
生徒
「名前がすごく長くて難しそうですね。プログラミング初心者でも使いこなせますか?」
先生
「大丈夫です。手順を一つずつ確認していけば、パソコンに慣れていない方でもちゃんと理解できます。基本から一緒に学んでいきましょう!」
1. JSONとシリアル化とは何か?
プログラミングを始めたばかりの方にとって、JSON(ジェイソン)という言葉は聞き慣れないかもしれません。JSONは「JavaScript Object Notation」の略で、テキストベースでデータを記述する形式の一つです。非常にシンプルで人間にも読みやすいため、現在では世界中のアプリやウェブサイトでデータのやり取りに使われています。
例えば、名前が「田中」、年齢が「25歳」という情報をJSONで書くと、以下のようになります。
{
"Name": "田中",
"Age": 25
}
そして、このJSON形式の文字列をC#のプログラムで扱える「オブジェクト(データの塊)」に変換したり、逆にオブジェクトをJSON文字列に変換したりすることをシリアル化(シリアライズ)と言います。今回紹介するDataContractJsonSerializerは、まさにこの変換作業を自動で行ってくれる便利な道具なのです。
2. DataContractJsonSerializerを使う準備
DataContractJsonSerializerを使用するためには、まず「参照設定」という準備が必要です。これは、C#の便利な機能が入った道具箱の中から、必要な道具を取り出す作業のようなものです。
具体的には、ソースコードの冒頭に以下の2行を記述する必要があります。これにより、プログラムの中でデータ契約(DataContract)という仕組みが使えるようになります。
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
また、プロジェクトの設定で「System.Runtime.Serialization.dll」というファイルが読み込まれるようになっている必要があります。Visual Studioなどの開発ツールを使っている場合は、基本的には自動で設定されますが、エラーが出る場合はここを確認してみましょう。これは、料理を作る前にキッチンに必要な調理器具が揃っているか確認するのと同じくらい大切なステップです。
3. データを整理するためのクラスを作ろう
JSONと変換するためには、C#側で「どんなデータを入れる箱が必要か」を定義しなければなりません。これをプログラミング用語でクラスと呼びます。クラスは、名前や住所などを書き込む「名簿のテンプレート」のようなものだと考えてください。
DataContractJsonSerializerを使う場合、このクラスに「これはJSONに変換するデータですよ」という印を付ける必要があります。それが[DataContract]と[DataMember]という属性です。
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
}
ここで出てくる属性(カッコで囲まれた部分)は、プログラムに対するメモ書きのような役割を果たします。DataContractはクラス全体に、DataMemberはJSONとして書き出したい個々の項目に付けます。これがないと、シリアル化する時に「どの項目をJSONに含めればいいの?」とプログラムが迷ってしまいます。
4. オブジェクトをJSONに変換する方法
いよいよ、C#のデータをJSON形式に書き出してみましょう。この工程をシリアル化と呼びます。例として、先ほど作ったPersonクラスにデータを入れて、それをJSONとして出力するコードを見てみましょう。
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
public class Program
{
public static void Main()
{
// 1. データの作成
Person p = new Person { Name = "佐藤", Age = 30 };
// 2. シリアライザーの用意
var serializer = new DataContractJsonSerializer(typeof(Person));
// 3. メモリ上にデータを書き出す準備
using (var ms = new MemoryStream())
{
// 4. JSONに変換(シリアル化)
serializer.WriteObject(ms, p);
// 5. 書き出された内容を文字列として表示
string jsonString = Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine(jsonString);
}
}
}
このコードを実行すると、画面に以下のように表示されます。
{"Age":30,"Name":"佐藤"}
コードの中にあるMemoryStream(メモリストリーム)は、一時的にデータを保存しておくための「仮想的なノート」のようなものです。そこにシリアライザーがJSONを書き込み、最後にそれを私たちが読める文字列として取り出しています。
5. JSONをオブジェクトに戻す方法
今度は反対に、インターネットなどから送られてきたJSON文字列を、C#のクラス形式に戻す方法を学びましょう。この工程を逆シリアル化(デシリアライズ)と呼びます。
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
public class Program
{
public static void Main()
{
// 1. 解析したいJSON文字列
string jsonText = "{\"Name\":\"鈴木\",\"Age\":20}";
// 2. 文字列をバイト配列に変換してストリームに入れる
byte[] bytes = Encoding.UTF8.GetBytes(jsonText);
using (var ms = new MemoryStream(bytes))
{
// 3. シリアライザーの用意
var serializer = new DataContractJsonSerializer(typeof(Person));
// 4. データを復元(逆シリアル化)
Person p = (Person)serializer.ReadObject(ms);
// 5. 結果の確認
Console.WriteLine("名前: " + p.Name);
Console.WriteLine("年齢: " + p.Age);
}
}
}
実行結果は以下の通りです。
名前: 鈴木
年齢: 20
ReadObjectという命令を使うことで、ただの文字列だったデータが再びPersonクラスのインスタンスとして息を吹き返します。これで、プログラムの中で「p.Name」といった形で簡単にデータを扱えるようになります。
6. リスト形式のデータを扱う方法
実際の開発では、一人のデータだけでなく、たくさんの人のデータをまとめて扱いたいことがあります。その場合は、List(リスト)という仕組みを使います。リストは、同じ種類のデータを複数並べて管理できる「棚」のようなものです。
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Json;
public class Program
{
public static void Main()
{
// リストに複数のデータを追加
List<Person> people = new List<Person>
{
new Person { Name = "田中", Age = 25 },
new Person { Name = "山田", Age = 40 }
};
// リスト用のシリアライザー
var serializer = new DataContractJsonSerializer(typeof(List<Person>));
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, people);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
実行結果を見ると、JSONの形式が少し変わり、全体が「[ ]」というカッコで囲まれていることがわかります。これがJSONにおける「配列(複数のデータの並び)」を表す記号です。DataContractJsonSerializerは、リスト構造も自動的に認識して正しいJSON形式に変換してくれます。
7. エラーを防ぐための注意点
プログラミングをしていると、思うように動かないことがあります。特にJSON操作で初心者がつまずきやすいポイントがいくつかあります。まず、クラスに[DataContract]などの属性を付け忘れることです。これがないと、シリアライザーは「何をすればいいかわからない」とパニックになってしまいます。
次に、JSONの項目名とクラスの変数名が一致しているかどうかです。基本的には大文字と小文字も区別されるため、注意が必要です。もし名前を変えたい場合は、属性を使って[DataMember(Name = "user_name")]のように指定することも可能です。これにより、C#側ではきれいな名前を使いつつ、JSON側では別の名前にするといった工夫ができます。
また、パソコンの操作に慣れていない方は、ファイルの読み書きでエラーが出ることがあります。ファイルが他のソフトで開かれていたり、書き込み禁止の場所に保存しようとしたりするとプログラムは止まってしまいます。これを防ぐために、例外処理という仕組みを使うのが一般的ですが、まずは正しい名前で正しい場所にデータを置くことから始めましょう。
8. 構造が複雑なJSONへの対応
データの中には、さらに別のデータが含まれているような重なり合った構造(入れ子構造)のものもあります。例えば、一人の人が複数の「趣味(Hobby)」を持っているような場合です。このような複雑なデータも、C#のクラスを階層状に作ることで対応可能です。
[DataContract]
public class User
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Profile Detail { get; set; }
}
[DataContract]
public class Profile
{
[DataMember]
public string Address { get; set; }
}
このように、クラスの中に別のクラスを定義することで、木が枝分かれするようにデータを整理できます。DataContractJsonSerializerは、どれだけ階層が深くても、全ての階層を辿ってJSONに変換してくれます。これは、複雑な書類を完璧にコピーしてくれる高性能な事務員のような存在です。
9. 文字コードと日本語の扱い
日本語を扱う際には、文字化けに気をつける必要があります。コンピュータは文字を数字として扱っていますが、その対応表を「文字コード」と呼びます。現在、インターネットの世界では「UTF-8」という文字コードが標準的に使われています。
今回紹介したサンプルコードでも、Encoding.UTF8という言葉が出てきましたね。これは「日本語の文字をUTF-8というルールで数字に変換してね」という意味です。もしこれを使わずに別のルールで変換してしまうと、読み取った時に「????」といった意味不明な文字になってしまうことがあります。日本語を含むデータを扱うときは、常にUTF-8を使うことを意識しましょう。これにより、世界中のどの環境でも正しく日本語が表示されるようになります。