JSON.NET で ISO8601 規格の日付時刻文字列を JObject に DateTimeOffset として読み込む
◆ はじめに
今さら JSON.NET かよって感じですが、仕事中にはまったのでメモ。 やりたいことは、JSON 内の ISO8601規格の日付時刻文字列を一旦 JObject に変換して、 変換した JObject から DatetimeOffset の値を取得したい。
◆ 何も考えずにやるとこうなる
素直に実装してみる。
Program.cs
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.IO; namespace DateTimeOffsetParseSample { class Program { static void Main(string[] args) { using (var stream = new StreamReader(@"Json\sample_data.json")) { var json = stream.ReadToEnd(); // json -> JObject var data = JsonConvert.DeserializeObject<JObject>(json); // JObject から DateTimeOffset 取得 var createdAtUtc = data.Value<DateTimeOffset>("created_at_utc"); var createdAtJst = data.Value<DateTimeOffset>("created_at_jst"); Console.WriteLine(createdAtUtc); Console.WriteLine(createdAtJst); } Console.ReadLine(); } } }
{ "created_at_utc": "2019-02-11T04:50:40Z", "created_at_jst": "2019-02-11T13:50:40+09:00" }
実行してみるとわかるが、var createdAtUtc = data.Value<DateTimeOffset>("created_at_utc");
の部分で例外が発生する。
System.InvalidCastException HResult=0x80004002 Message='System.DateTime' から 'System.DateTimeOffset' への無効なキャストです。 Source=mscorlib
なんでや。Value<DateTimeOffset>
してるのに。
◆ 解決方法
結論 DeserializeObject の引数で、日付変換設定を渡してあげれば良い。
Program.cs
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.IO; namespace DateTimeOffsetParseSample { class Program { static void Main(string[] args) { using (var stream = new StreamReader(@"Json\sample_data.json")) { var json = stream.ReadToEnd(); // json -> JObject var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.DateTimeOffset, DateFormatHandling = DateFormatHandling.IsoDateFormat, DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind }; var data = JsonConvert.DeserializeObject<JObject>(json, settings); // JObject から DateTimeOffset 取得 var createdAtUtc = data.Value<DateTimeOffset>("created_at_utc"); var createdAtJst = data.Value<DateTimeOffset>("created_at_jst"); Console.WriteLine(createdAtUtc); Console.WriteLine(createdAtJst); } Console.ReadLine(); } } }
結果
2019/02/11 4:50:40 +00:00 2019/02/11 13:50:40 +09:00
めでたし、めでたし。
◆ まとめ
こんなことやりたい人がどれだけいるのかはわからないけど、知ってればなんてことない話。 ちなみに、JObject 経由しない場合だと、何も考えずに変換できる。なんでや。 あと、JSON.NET のキャラクターはなんかむかつく。以上。