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

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

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

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

# やり方
DataContractJsonSerializerクラスをつかう。

# 準備
参照に`System.Runtime.Serialization`を追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/a6c5167e-e137-08fd-988b-8a9df5decd41.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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/2da30098-72b9-80b5-9428-072b98873660.png)
※サンプルのTestData.jsonをちょっといじって、2つ目のデータの方の「Large」を試しに削ったjsonを呼んだ時のウォッチ

# jsonメモ

- `[`と`]`でくくったところは**配列**になる。
 - クラスで書くと、`List<〇〇>`になる。
 - jsonの先頭が`[`で配列の場合は、`new DataContractJsonSerializer(typeof(List<PointData>));`のように、コンストラクタに渡す型が`List<〇〇>`になる。
 - 先頭以外だと、クラスのプロパティの型が`List<〇〇>`になる。
- `{`と`}`でくくったところは**オブジェクト**になる。
 - オブジェクトは、C#ではクラスやプロパティに該当する。
- 今回サンプルにはないが、数値以外にもjsonにはデータを持たせられる様子。([こちら](https://soseiji-memo.hatenablog.com/entry/json)によると、下表のようなものを持たせられる)

|データ型|備考|
|---|---|
|数値||
|文字列|ダブルクォーテーションでくくる。|
|真偽値|true or false。小文字にする。|
|配列|コンマ区切りの角かっこでくくる。|
|オブジェクト|コンマ区切りの波かっこでくくる。キーと値のペアをコロンで対にする。キーはダブルクォーテーションでくくる。|
|null|デシリアライズ時、C#のクラスにはあるのにjsonにないようなときに、jsonを読むとnullになる|


# C#のクラスとjsonの対応付けイメージ
今回のサンプルのC#とjsonの対応付けは下記のようなイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/67a33ba6-b402-fcb7-669a-58159194a512.png)

# 備考
データを入れるクラスに`[DataContract]`、プロパティに`[DataMember]`をつけてるが、これらをつけてなくても問題なくシリアライズ/デシリアライズできた。
その辺の、アトリビュートをつけたとき、つけてないときの動作の比較は[こちらのサイト](http://mokake.hatenablog.com/entry/2017/09/12/195656)が超絶詳しい。そちらを参照。

# 追記(20/01/06) データ用クラスの簡単な作り方
jsonデータのためのクラスを簡単につくる方法があることが分かった。
下記の記事を参照。

→[DataContractJsonSerializerで読み書きするjsonデータのためのクラスを簡単につくる](https://qiita.com/tera1707/items/8033a5e50a0bcae30165)

# 参考
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