.NET で JSON を読んだ時に認知していないデータを保持したい
.NET 7 で System.Text.Json 使ったときの話です
最近のシステム間のデータのやり取りでは結構な割合でJSONを使うことがあります。ちょっと前までXMLだった気がしますがどんどんJSONになっていますね。(表記する時JSON なのか Json なのか json なのかよくわからない)
想定
{ "a":1, "b":2 }
を受け取って、"a" をインクリメントして返したい場合、みたいな感じ
var json = @"{""a"":1,""b"":2}"; var t = JsonSerializer.Deserialize<Test>(json); t.A++; Console.WriteLine(JsonSerializer.Serialize(t)); // {"a":2,"b":2} public class Test { [JsonPropertyName("a")] public int A { get; set; } [JsonPropertyName("b")] public int B { get; set; } }
これでいいですね?
想定外
JSON や XML は拡張性があるのが売りです。ほかのシステムで上記 JSON を拡張してしまいました
{ "a":1, "b":2, "c":3, "d":{ "e":4 }}
これを先ほどのアプリに読み込ませると、当然ですがDeserialize時に c 以降が消えてしまいます
var json = @"{""a"":1,""b"":2,""c"":3,""d"":{""e"":4}}"; var t = JsonSerializer.Deserialize<Test>(json); t.A++; Console.WriteLine(JsonSerializer.Serialize(t)); // {"a":2,"b":2}
解決策
クラスの定義(↑ではTest)にJsonExtensionDataAttribute
を付けた Dictionary を追加してあげます
var json = @"{""a"":1,""b"":2,""c"":3,""d"":{""e"":4}}"; var t = JsonSerializer.Deserialize<Test>(json); t.A++; Console.WriteLine(JsonSerializer.Serialize(t)); // {"a":2,"b":2,"c":3,"d":{"e":4}} public class Test { [JsonPropertyName("a")] public int A { get; set; } [JsonPropertyName("b")] public int B { get; set; } [JsonExtensionData] public Dictionary<string, object> AdditionalData { get; set; } }
できました
XMLの場合
System.Xml.Serialization
を使う場合は同じような感じで
[XmlAnyElement] [XmlText] public XmlNode[] ChildNodes { get; set; }
で行けるとおもいます
まとめ
JSON も XML も 解決策は stackoverflow で見つけたんですが、日本語でもどういうキーワードで調べればいいのかがよくわからない問題だったので英語ではさらに苦労しました、という話でした(?)