LoginSignup
12

More than 1 year has passed since last update.

[C#] .NET標準のDataContractJsonSerializerクラスを使ってjsonを読み書きする

Last updated at Posted at 2019-10-25

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

json関連記事
https://qiita.com/tera1707/items/4fda73d86eded283ec4f#json

やりたいこと

jsonファイルを読み書きするときに、使えるライブラリがいくつかあるようだが、できれば.netで標準で使えるものを使って行いたい。

やり方

DataContractJsonSerializerクラスをつかう。

準備

参照にSystem.Runtime.Serializationを追加する。
image.png

サンプル(.cs)

jsonファイルからデータを読んで、クラスオブジェクトに展開する。(デシリアライズ)
そのあと、クラスオブジェクトの中身をファイルにjson文字列として保存する。(シリアライズ)

サンプル.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;

namespace JsonTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // デシリアライズ(jsonファイル→クラスオブジェクト)
            string jsonFilePath = @"TestData.json";
            var data = new List<PointData>();

            using (var ms = new FileStream(jsonFilePath, FileMode.Open))
            {
                var serializer = new DataContractJsonSerializer(typeof(List<PointData>));
                data = (List<PointData>)serializer.ReadObject(ms);
            }

            // シリアライズ(クラスオブジェクト→jsonファイル)
            string jsonFilePathOut = @"TestDataOut.json";

            using (var stream = new MemoryStream())
            using (var fs = new FileStream(jsonFilePathOut, FileMode.Create))
            using (var sw = new StreamWriter(fs))
            {
                var serializer = new DataContractJsonSerializer(typeof(List<PointData>));
                serializer.WriteObject(stream, data);
                var str2write = Encoding.UTF8.GetString(stream.ToArray());
                sw.Write(str2write);
            }

            // 終わり
            Console.WriteLine("json読み書き完了");
            Console.ReadLine();
        }
    }

    [DataContract]
    public class PointData
    {
        [DataMember]
        public List<double> small { get; set; }

        [DataMember]
        public List<double> large { get; set; }
    }
}

サンプル(.json)

使ったjsonはこちら

TestData.json
[
    {
        "small": [
            123.456,
            789.012
        ],
        "large": [
            987.654,
            654.321
        ]
    },
    {
        "small": [
            111.456,
            222.012
        ],
        "large": [
            333.654,
            444.321
        ]
    }
]

デシリアライズしたときのウォッチ
image.png
※サンプルのTestData.jsonをちょっといじって、2つ目のデータの方の「Large」を試しに削ったjsonを呼んだ時のウォッチ

jsonメモ

  • []でくくったところは配列になる。
    • クラスで書くと、List<〇〇>になる。
    • jsonの先頭が[で配列の場合は、new DataContractJsonSerializer(typeof(List<PointData>));のように、コンストラクタに渡す型がList<〇〇>になる。
    • 先頭以外だと、クラスのプロパティの型がList<〇〇>になる。
  • {}でくくったところはオブジェクトになる。
    • オブジェクトは、C#ではクラスやプロパティに該当する。
  • 今回サンプルにはないが、数値以外にもjsonにはデータを持たせられる様子。(こちらによると、下表のようなものを持たせられる)
データ型 備考
数値
文字列 ダブルクォーテーションでくくる。
真偽値 true or false。小文字にする。
配列 コンマ区切りの角かっこでくくる。
オブジェクト コンマ区切りの波かっこでくくる。キーと値のペアをコロンで対にする。キーはダブルクォーテーションでくくる。
null デシリアライズ時、C#のクラスにはあるのにjsonにないようなときに、jsonを読むとnullになる

C#のクラスとjsonの対応付けイメージ

今回のサンプルのC#とjsonの対応付けは下記のようなイメージ。
image.png

備考

データを入れるクラスに[DataContract]、プロパティに[DataMember]をつけてるが、これらをつけてなくても問題なくシリアライズ/デシリアライズできた。
その辺の、アトリビュートをつけたとき、つけてないときの動作の比較はこちらのサイトが超絶詳しい。そちらを参照。

追記(20/01/06) データ用クラスの簡単な作り方

jsonデータのためのクラスを簡単につくる方法があることが分かった。
下記の記事を参照。

DataContractJsonSerializerで読み書きするjsonデータのためのクラスを簡単につくる

参考

DataContractJsonSerializerの詳細動作
>本クラスの使い方から、[DataContract]をつけたとき、つけないときの動作の比較など、わかりやすく解説されてる。このページ見れば全部わかる。
http://mokake.hatenablog.com/entry/2017/09/12/195656

DataContractJsonSerializer Class (MS Docs)
https://docs.microsoft.com/ja-jp/dotnet/api/system.runtime.serialization.json.datacontractjsonserializer?view=netframework-4.8

jsonのデータの種類
https://soseiji-memo.hatenablog.com/entry/json

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12