PR

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

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

[C#] クラスオブジェクトとJSON文字列の相互変換(シリアライズ、デシリアライズ)
JsonSerializerを使ってクラスオブジェクトをJSON文字列に変換する方法、JSON文字列をクラスオブジェクトに変換する方法のサンプルです。 クラスオブジェクト ⇒ JSON文字列 をシリアライズJSON文字列 ⇒ クラスオブジェ...

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

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

[C#] Dictionaryや匿名クラスをJSON文字列に変換する
こちらの記事ではクラスオブジェクトとJSONファイルの相互変換について書きました。 が、わざわざJSONの定義に合ったクラスを定義するのはめんどくさいということでDictionaryや匿名クラスを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# 記事まとめページに戻る(他のサンプルコードもこちら)

C# プログラミング講座
C#についての記事まとめページです。開発環境VisualStudioのインストール方法や使い方、プログラミングの基礎知識についてや用語説明の記事一覧になっています。講座の記事にはすぐに実行できるようにサンプルコードを載せています。

コメント