未知の Json を扱う一連の記事をまとめた記事を書きました。
こちらの記事で一気読みできます。
■ 現行世代の Json API / System.Text.Json
Json を扱う際には .NET Framework 時代には Json.NET というライブラリがよく使われていました。今の時代 (.NET Core 3 以降) は System.Text.Json
を使用します。
未知の Json を扱う記事を以前に書きました。
しかし、少し嬉しくないことに多段の構造を持った Json を System.Dynamic.ExpandoObject
にデシリアライズしてもあまり嬉しい感じではありませんでした。
■ コンバートするコード
あまり嬉しくなかったので、雑に JsonDucument で デシリアライズした後に ExpandoObject に変えるコードを書いてみました。
static System.Dynamic.ExpandoObject Parse(string json) { using var document = System.Text.Json.JsonDocument.Parse(json); return toExpandoObject(document.RootElement); static object propertyValue(System.Text.Json.JsonElement elm) => elm.ValueKind switch { System.Text.Json.JsonValueKind.Null => null, System.Text.Json.JsonValueKind.Number => elm.GetDecimal(), System.Text.Json.JsonValueKind.String => elm.GetString(), System.Text.Json.JsonValueKind.False => false, System.Text.Json.JsonValueKind.True => true, System.Text.Json.JsonValueKind.Array => elm.EnumerateArray().Select(m => propertyValue(m)).ToArray(), _ => toExpandoObject(elm), }; static System.Dynamic.ExpandoObject toExpandoObject(System.Text.Json.JsonElement elm) => elm.EnumerateObject() .Aggregate( new System.Dynamic.ExpandoObject(), (exo, prop) => { ((IDictionary<string, object>)exo).Add(prop.Name, propertyValue(prop.Value)); return exo; }); }
理屈は、まあ普通の C# コードなので読んでもらえば分かると思います。
使い方
メソッドなので普通に使えます。
dynamic expandoObject = Parse( @"{ ""prop1"": ""value1"", ""prop2"": 2, ""prop3"": { ""p31"": 31 , ""p32"": [1, ""2"", { ""p321"": ""value321"", ""p322"": ""value322"" } ] }}");
試しに、プロパティを追加したり削除したりなどして、シリアライズして結果を見てみましょう。
dynamic expandoObject = Parse( @"{ ""prop1"": ""value1"", ""prop2"": 2, ""prop3"": { ""p31"": 31 , ""p32"": [1, ""2"", { ""p321"": ""value321"", ""p322"": ""value322"" } ] }}"); // プロパティを追加してみる expandoObject.prop3.p33 = 33; // プロパティを削除してみる ((IDictionary<string, object>)expandoObject.prop3).Remove("p31"); // シリアライズしてみる Console.WriteLine( System.Text.Json.JsonSerializer.Serialize(expandoObject) ); // {"prop1":"value1","prop2":2,"prop3":{"p32":[1,"2",{"p321":"value321","p322":"value322"}],"p33":33}} と出力される
出力結果
{"prop1":"value1","prop2":2,"prop3":{"p32":[1,"2",{"p321":"value321","p322":"value322"}],"p33":33}}
それっぽく動いているようです。