こちらの記事ではクラスオブジェクトと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# 記事まとめページに戻る(他のサンプルコードもこちら)
コメント