[C#] JSON文字列をDictionaryに変換する

こちらの記事ではクラスオブジェクトとJSONファイルの相互変換について書きました。

が、わざわざJSONの定義に合ったクラスを定義するのはめんどくさいということで、なんとかいい感じにDicitonaryとかにデシリアライズできないかという記事です。

ちなみにDictonary、匿名クラスをJSON文字列にシリアライズする記事はこちら、

スポンサーリンク

ちょっと面倒そうだ(急ぐ人は飛ばしてください)

調べたところ少し面倒でパッと変換とはいかず、ひと手間必要な感じです。

デシリアライズにはJsonSerializer.Deserialize<T>メソッドを使おうと思うのですが、Tの部分をDictionary<string, object>とかにしてデシリアライズするとobjectにはJsonElement構造体というよくわからないものが変換されて入ります。

んで、JsonElementはValueKindプロパティでデータ型を調べて、型に合ったメソッド(GetBoolean、GetDecimalなど)を使って値を取得するらしい。

なので、データ型を調べて変換するメソッドを自作してdymanic型に入れて返そうと思います。
dynamic型ってなに?という方は、[C# 入門] 動的型付け変数(dynamic型)についてを見てください。

スポンサーリンク

とりあえずやってみる(急ぐ人はここから)

こんな感じになりました。
JSON文字列をDictionary<string, dynamic>型に変換しています。
メソッドが2つになったのでJsonToLibaryというクラスを作ってまとめています。

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Linq;

class Program
{
    public static void Main()
    {
        // JSON文字列を作るためのDictionary
        var tmp = new Dictionary<string, object> {
            { "key1", 10 },
            { "key2", false },
            { "key3", new int[] { 1, 2, 3 } },
            { "key4", new List<string> { "a", "b", "c" } },
            { "key5", new { Name = "YasNote", Age = 99 } },
            { "key6", DateTime.Now.ToString() },
        };
        // JSON文字列を作成
        var jsonstr = JsonSerializer.Serialize(tmp);

        // JSON文字列をDictionary<string, dynamic>に変換
        var dic = JsonToLibary.ParseJson(jsonstr);

        // 結果を表示
        Console.WriteLine(dic["key1"]);         // 10
        Console.WriteLine(dic["key2"]);         // False
        Console.WriteLine(dic["key3"][1]);      // 2
        Console.WriteLine(dic["key4"][2]);      // c
        Console.WriteLine(dic["key5"]["Name"]); // YasNote
        Console.WriteLine(dic["key6"]);

        // 項目追加してシリアライズしてみる
        dic["key7"] = new { Name = "Stratocaster", Age = 100 };
        var jsonstr2 = JsonSerializer.Serialize(dic);
        Console.WriteLine(jsonstr2);
    }
}

class JsonToLibary 
{
    // JSON文字列をDictionary<string, dynamic>型に変換するメソッド
    public static Dictionary<string, dynamic> ParseJson(string json)
    {
        // とりあえずJSON文字列をDictionary<string, JsonElement>型に変換
        var dic = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);

        // JsonElementから値を取り出してdynamic型に入れてDictionary<string, dynamic>型で返す
        return dic.Select(d => new { key = d.Key, value = ParseJsonElement(d.Value) })
            .ToDictionary(a => a.key, a => a.value);
    }

    // JsonElementの型を調べて変換するメソッド
    private static dynamic ParseJsonElement(JsonElement elem)
    {
        // データの種類によって値を取得する処理を変える
        return elem.ValueKind switch
        {
            JsonValueKind.String => elem.GetString(),
            JsonValueKind.Number => elem.GetDecimal(),
            JsonValueKind.False  => false,
            JsonValueKind.True   => true,
            JsonValueKind.Array  => elem.EnumerateArray().Select(e => ParseJsonElement(e)).ToList(),
            JsonValueKind.Null   => null,
            JsonValueKind.Object => ParseJson(elem.GetRawText()),
            _ => throw new NotSupportedException(),
        };
    }
}

結果表示はこんな感じ。

10
False
2
c
YasNote
2020/06/14 21:54:33
{"key1":10,"key2":false,"key3":[1,2,3],"key4":["a","b","c"],"key5":{"Name":"YasNote","Age":99},"key6":"2020/06/14 22:05:42","key7":{"Name":"Stratocaster","Age":100}}

23行目でJSON文字列をDictionaryに変換しています。
あとはDictionaryからKey名を指定して値を取り出します。値はdynamic型なので必要に応じてキャストしたりしてください。

34~36行目でDictionaryに項目を追加してJSON文字列にシリアライズしています。

このサンプルでは日付のデータはstring型で取り込まれるので必要に応じて変換してください。


C# プログラミング講座に戻る

コメント

タイトルとURLをコピーしました