C# PR

XmlSerializerでC#オブジェクトをXML形式で保存する方法

記事内に商品プロモーションを含む場合があります

こんにちは!

C#でオブジェクトをXML形式で保存したり、XMLファイルからオブジェクトを復元したりする場面に遭遇することがありますよね。

XmlSerializerって何だろう?どうやって使うの?
オブジェクトをXMLに変換する方法がわからない…
設定ファイルをXMLで管理したいけど、どうすればいい?

C#でのオブジェクトとXMLの相互変換において、このような疑問をお持ちではないでしょうか。

この記事では、C#の「XmlSerializer」について、基本概念から具体的な使い方、実用的な応用例までを詳しく解説します。

この記事は次のような方におすすめです。

この記事はこんな人におすすめ!
  • C#でXMLファイルの読み書きをしたい方
  • オブジェクトのシリアル化について学びたい方
  • 設定ファイルや設定データをXML形式で管理したい開発者
  • XMLとオブジェクトの相互変換を効率化したい方
  • .NET Frameworkのシリアル化機能に興味がある方

この記事を読めば、XmlSerializerの仕組みが理解でき、実際のプロジェクトですぐに活用できるスキルが身につきます。C#でのデータ管理を効率化して、より実用的なアプリケーションを作れるようになりますよ!

「C#でXML操作をマスターしたい方」「オブジェクト指向とXMLを組み合わせたい方」は、ぜひ参考にしてください。

それでは、順を追って詳しく見ていきましょう!

XmlSerializerとは何か

XmlSerializerは、C#オブジェクトとXMLドキュメントを相互に変換するための.NETクラスです。System.Xml.Serialization名前空間に含まれており、.NET Framework 1.1から利用可能な歴史の長い機能です。

XmlSerializerの基本的な特徴は以下の通りです。

  • オブジェクトをXMLドキュメントに変換する(シリアル化)
  • XMLドキュメントをオブジェクトに変換する(デシリアル化)
  • 属性を使ってXML出力をカスタマイズできる
  • 設定ファイルやデータ交換で広く利用されている
  • W3C XML Schema Definition(XSD)1.0準拠のXMLを生成する

XmlSerializerの基本的な使い方

XmlSerializerを使用するためには、まず必要な名前空間をインポートします。

using System;
using System.IO;
using System.Xml.Serialization;

シンプルなクラスのシリアル化

まず、最もシンプルな例から見ていきましょう。

public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }
  public string Email { get; set; }
}

class Program
{
  static void Main()
  {
    // シリアル化するオブジェクトを作成
    var person = new Person
    {
      Name = "田中太郎",
      Age = 30,
      Email = "tanaka@example.com"
    };

    // XmlSerializerを作成
    var serializer = new XmlSerializer(typeof(Person));

    // XMLファイルに保存
    using (var writer = new FileStream("person.xml", FileMode.Create))
    {
      serializer.Serialize(writer, person);
    }

    Console.WriteLine("XMLファイルに保存しました。");
  }
}

この例では、Personクラスのオブジェクトをperson.xmlファイルに保存します。生成されるXMLは以下のような形になります。

<?xml version="1.0" encoding="utf-8"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>田中太郎</Name>
  <Age>30</Age>
  <Email>tanaka@example.com</Email>
</Person>

デシリアル化(XMLからオブジェクトへの復元)

保存したXMLファイルからオブジェクトを復元する方法は以下の通りです。

static void LoadFromXml()
{
  var serializer = new XmlSerializer(typeof(Person));

  // XMLファイルから読み込み
  using (var reader = new FileStream("person.xml", FileMode.Open))
  {
    var person = (Person)serializer.Deserialize(reader);

    Console.WriteLine($"名前: {person.Name}");
    Console.WriteLine($"年齢: {person.Age}");
    Console.WriteLine($"メール: {person.Email}");
  }
}

XmlSerializerの制限と注意点

XmlSerializerを使用する際には、いくつかの制限があります。

シリアル化できる要素の制限

XmlSerializerでシリアル化できるのは、以下の要素に限定されます。

  • パブリック(public)なフィールド
  • パブリック(public)なプロパティ(getterとsetterの両方が必要)
  • パラメータなしのコンストラクタが必要

基本的な制限の例

public class Example
{
  public string PublicField;          // ✓ シリアル化される
  public string PublicProperty { get; set; }  // ✓ シリアル化される

  private string privateField;       // ✗ シリアル化されない
  internal string internalField;     // ✗ シリアル化されない

  public string ReadOnlyProperty { get; }     // ✗ setterがないため不可
}

XML出力をカスタマイズする属性

XmlSerializerでは、さまざまな属性を使ってXML出力をカスタマイズできます。

主要な属性一覧

属性名 説明
XmlRoot ルート要素の名前や名前空間を指定
XmlElement 要素名を指定
XmlAttribute XML属性として出力
XmlIgnore シリアル化対象から除外
XmlArray 配列の親要素名を指定
XmlArrayItem 配列の各要素名を指定

属性を使ったカスタマイズの例

[XmlRoot("商品")]
public class Product
{
  [XmlAttribute("ID")]
  public int Id { get; set; }

  [XmlElement("商品名")]
  public string Name { get; set; }

  [XmlElement("価格")]
  public decimal Price { get; set; }

  [XmlIgnore]
  public string InternalCode { get; set; }  // XMLに出力されない

  [XmlArray("カテゴリリスト")]
  [XmlArrayItem("カテゴリ")]
  public string[] Categories { get; set; }
}

このクラスを使用すると、以下のようなXMLが生成されます。

<?xml version="1.0" encoding="utf-8"?>
<商品 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="1">
  <商品名>ノートPC</商品名>
  <価格>89800</価格>
  <カテゴリリスト>
    <カテゴリ>電子機器</カテゴリ>
    <カテゴリ>コンピュータ</カテゴリ>
  </カテゴリリスト>
</商品>

複雑なオブジェクト構造のシリアル化

実際のアプリケーションでは、複数のクラスを組み合わせた複雑な構造をシリアル化することがよくあります。

public class Order
{
  [XmlElement("注文日")]
  public DateTime OrderDate { get; set; }

  [XmlElement("顧客")]
  public Customer Customer { get; set; }

  [XmlArray("注文商品")]
  [XmlArrayItem("商品")]
  public List<OrderItem> Items { get; set; }

  [XmlElement("合計金額")]
  public decimal TotalAmount { get; set; }
}

public class Customer
{
  [XmlAttribute("ID")]
  public int Id { get; set; }

  [XmlElement("名前")]
  public string Name { get; set; }

  [XmlElement("メール")]
  public string Email { get; set; }
}

public class OrderItem
{
  [XmlElement("商品名")]
  public string ProductName { get; set; }

  [XmlElement("数量")]
  public int Quantity { get; set; }

  [XmlElement("単価")]
  public decimal UnitPrice { get; set; }
}

このような階層構造のあるクラスでも、XmlSerializerは自動的に適切なXML構造を生成します。

XML出力のフォーマット制御

XMLの出力フォーマットを細かく制御したい場合は、XmlWriterSettingsクラスを使用します。

public static void SaveWithFormatting<T>(T obj, string filePath)
{
  var settings = new XmlWriterSettings
  {
    Indent = true,                    // インデントを付ける
    IndentChars = "  ",              // インデントに使う文字
    OmitXmlDeclaration = true,       // XML宣言を省略
    Encoding = Encoding.UTF8         // エンコーディング指定
  };

  var namespaces = new XmlSerializerNamespaces();
  namespaces.Add("", "");              // デフォルト名前空間を除去

  var serializer = new XmlSerializer(typeof(T));

  using (var writer = XmlWriter.Create(filePath, settings))
  {
    serializer.Serialize(writer, obj, namespaces);
  }
}

文字列との相互変換

ファイルではなく文字列としてXMLを扱いたい場合の例です。

public static string SerializeToString<T>(T obj)
{
  var serializer = new XmlSerializer(typeof(T));

  using (var writer = new StringWriter())
  {
    serializer.Serialize(writer, obj);
    return writer.ToString();
  }
}

public static T DeserializeFromString<T>(string xmlString)
{
  var serializer = new XmlSerializer(typeof(T));

  using (var reader = new StringReader(xmlString))
  {
    return (T)serializer.Deserialize(reader);
  }
}

パフォーマンス考慮事項

XmlSerializerを使用する際のパフォーマンス面での注意点があります。

XmlSerializerのキャッシュ化

同じ型に対してXmlSerializerを繰り返し作成するのは効率的ではありません。以下のようにキャッシュして再利用するのが推奨されます。

public static class XmlSerializerCache
{
  private static readonly Dictionary<Type, XmlSerializer> Cache =
    new Dictionary<Type, XmlSerializer>();

  public static XmlSerializer GetSerializer(Type type)
  {
    if (!Cache.ContainsKey(type))
    {
      Cache[type] = new XmlSerializer(type);
    }
    return Cache[type];
  }
}

大量データの処理での注意点

XmlSerializerは大量のデータを処理する際に以下の特徴があります。

  • 初回の実行時にアセンブリの動的生成が行われるため、起動が遅い場合があります
  • メモリ消費量が比較的多くなる可能性があります
  • 複雑なオブジェクト構造では処理時間が長くなることがあります

他のシリアル化方法との比較

C#には複数のシリアル化手法があります。それぞれの特徴を比較してみましょう。

機能 XmlSerializer System.Text.Json Newtonsoft.Json BinaryFormatter
フォーマット XML JSON JSON Binary
可読性 高い 高い 高い 低い
ファイルサイズ 大きい 小さい 小さい 最小
パフォーマンス 普通 高い 普通 高い
カスタマイズ性 高い 普通 高い 低い
.NET サポート 全バージョン .NET Core 3.0以降 NuGet パッケージ .NET Framework のみ

実践的な使用例。設定ファイルの管理

XmlSerializerの実践的な使用例として、アプリケーションの設定ファイル管理があります。

[XmlRoot("アプリ設定")]
public class AppConfig
{
  [XmlElement("データベース")]
  public DatabaseConfig Database { get; set; }

  [XmlElement("ログ設定")]
  public LogConfig Logging { get; set; }

  [XmlArray("接続先リスト")]
  [XmlArrayItem("接続先")]
  public List<ServerConfig> Servers { get; set; }
}

public class DatabaseConfig
{
  [XmlElement("接続文字列")]
  public string ConnectionString { get; set; }

  [XmlElement("タイムアウト")]
  public int Timeout { get; set; }
}

public class LogConfig
{
  [XmlElement("レベル")]
  public string Level { get; set; }

  [XmlElement("ファイルパス")]
  public string FilePath { get; set; }
}

public class ServerConfig
{
  [XmlAttribute("名前")]
  public string Name { get; set; }

  [XmlElement("URL")]
  public string Url { get; set; }

  [XmlElement("ポート")]
  public int Port { get; set; }
}

この設定クラスを使用すると、以下のような読みやすいXML設定ファイルを作成できます。

<?xml version="1.0" encoding="utf-8"?>
<アプリ設定 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <データベース>
    <接続文字列>Server=localhost;Database=MyApp;Trusted_Connection=true;</接続文字列>
    <タイムアウト>30</タイムアウト>
  </データベース>
  <ログ設定>
    <レベル>Info</レベル>
    <ファイルパス>C:\Logs\app.log</ファイルパス>
  </ログ設定>
  <接続先リスト>
    <接続先 名前="本番サーバー">
      <URL>https://api.example.com</URL>
      <ポート>443</ポート>
    </接続先>
    <接続先 名前="テストサーバー">
      <URL>https://test-api.example.com</URL>
      <ポート>443</ポート>
    </接続先>
  </接続先リスト>
</アプリ設定>

エラーハンドリングとデバッグ

XmlSerializerを使用する際のエラーハンドリングも重要です。

public static T SafeDeserialize<T>(string filePath) where T : class
{
  try
  {
    var serializer = new XmlSerializer(typeof(T));

    using (var reader = new FileStream(filePath, FileMode.Open))
    {
      return (T)serializer.Deserialize(reader);
    }
  }
  catch (FileNotFoundException)
  {
    Console.WriteLine($"ファイルが見つかりません: {filePath}");
    return null;
  }
  catch (InvalidOperationException ex)
  {
    Console.WriteLine($"XML形式が正しくありません: {ex.Message}");
    return null;
  }
  catch (Exception ex)
  {
    Console.WriteLine($"予期しないエラーが発生しました: {ex.Message}");
    return null;
  }
}

セキュリティ上の注意点

XmlSerializerを使用する際のセキュリティ面での注意点があります。

  • 信頼できないソースからのXMLファイルはデシリアル化しない
  • 外部からの入力を直接デシリアル化する場合は、入力値の検証を行う
  • 機密データを含むオブジェクトをXMLファイルに保存する際は、暗号化を検討する
  • 一時ファイルの作成場所や権限に注意する

キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇、有給6日取得で特別休暇付与)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、お問い合わせフォーム、またはX (旧Twitter)、InstagramのDMでお気軽にご相談ください♪

まとめ

C# XmlSerializerは、オブジェクトとXMLの相互変換を効率的に行うための強力なツールです。

  • オブジェクトをXMLファイルに保存し、XMLファイルからオブジェクトを復元できます
  • 属性を使ってXML出力を細かくカスタマイズできます
  • 設定ファイル管理や設定データの永続化に適しています
  • パフォーマンス面での考慮事項やセキュリティ上の注意点があります
  • 他のシリアル化手法と比較して、XML形式での可読性が高いのが特徴です

XML形式でのデータ管理が必要な場面では、XmlSerializerの使用を検討してみてください。特に設定ファイルや設定データの管理では、人間が読みやすく編集しやすいXML形式の利点を活かせます。ただし、大量のデータを高速に処理する必要がある場合は、JSONやバイナリ形式の利用も検討することをお勧めします。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です