2016-12-21 3 views
1

Newtonsoft.Json.Linq名前空間を使用してJSONを解析すると、日付値を選択すると元のJSONとは異なる形式の文字列が返されます。これを引き起こしているのは何ですか?例えばC#でNewtonsoft.Json.Linqを使用してJSONをクエリすると、日付文字列が操作される

JSON

[ 
    { 
    ... 
    "commit": { 
     ... 
     "committer": { 
     "name": "GitHub", 
     "email": "[email protected]", 
     "date": "2016-12-19T11:53:13Z" 
     }, 
     ... 
    } 
    ... 
    } 
    ... 
] 

C#

... 
List<Commit> commits = new List<Commit>(); 
JArray commitsArray = JArray.Parse(rawCommits); 
... 
foreach (var entry in commitsArray) 
{ 
    DateTime date; 
    CultureInfo provider = CultureInfo.InvariantCulture; 
    string format = "MM/dd/yyyy HH:mm:ss"; 

    try 
    { 
     date = DateTime.ParseExact((string)entry["commit"]["committer"]["date"], format, provider); 
    } 
    catch (FormatException ex) 
    { 
     date = new DateTime(0); 
    } 
    ... 
} 
... 

rawCommitsは生JSONの文字列表現がMicrosoft.AspNetCore.WebUtilities.HttpRequestStreamReader()を用いて得られます。

(string)entry["commit"]["committer"]["date"]は、JSONの場合と同じ文字列を"yyyy-MM-ddTHH:mm:ssz"という形式で返しますが、上記のコードでは"MM/dd/yyyy HH:mm:ss"という形式で返されると考えています。なぜ形式が変更されたのか、時刻とタイムゾーンの識別子に何が起こったのですか?

私が考えることができるのは、JArray.Parse(string)への呼び出しが日付を識別して操作することだけです。これは本当ですか?もしそうなら、それは確かに望ましくない振る舞いですか?そうでない場合、何が起こっているのですか?

編集 これはproject.jsonファイルへ"Microsoft.AspNetCore.Mvc": "1.1.0"を追加し、ネットコアコンソールアプリケーションでは、次の例で製造することができる:それはあるので面白いです19/12/2016 11:53:13の出力、で

using Newtonsoft.Json.Linq; 
using System; 

namespace JsonExample 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      string json = "{\"date\": \"2016-12-19T11:53:13Z\"}"; 
      JToken jToken = JToken.Parse(json); 

      Console.WriteLine(jToken["date"]); 
      Console.ReadLine(); 
     } 
    } 
} 

さらに別のフォーマット(dd/MM/yyyy HH:mm:ss)。これはおそらくローカリゼーションの設定と関係がありますか?もしそうなら、なぜですか? IIS Expressが上記のコードを実行したマシンと同じマシンで実行されていることを考えると、混乱しますが、ホストマシンのローカリゼーションが必要になると思います。また、私の開発マシンとは異なるローカライゼーションを使用してサーバーにデプロイすると、元のポストの書式指定子が例外となるため、new DateTime(0)の値になります。それは私が理解していないものですか?

答えて

2

あなたは正しいです、JArray.Parseへの呼び出しは、自動的に日付を解析しています(by design)。

私はあなたが直接リーダーを使用する必要が生の文字列で取得すると思う:

var s = @"[{ 
      ""commit"": { 
       ""committer"": { 
        ""name"": ""GitHub"", 
        ""email"": ""[email protected]"", 
        ""date"": ""2016-12-19T11:53:13Z"" 
       } 
      } 
     } 
    ]"; 

    using (var sr = new StringReader(s)) 
    using (var jr = new JsonTextReader(sr) { DateParseHandling = DateParseHandling.None }) 
    { 
     var arr = JArray.ReadFrom(jr); 

     foreach (var entry in arr) 
     { 
      Console.WriteLine(entry["commit"]["committer"]["date"].ToString()); // 2016-12-19T11:53:13Z 
     } 
    } 
+0

ありがとうございます。この例では、この問題に関するGitHub対話へのリンクと例の両方があります。望ましくない効果のように思えますが、図書館の作者がその機能を好きなら、どうなるのでしょうか? –

+0

私が目指している最も簡単な解決策は、結果を 'DateTime'にキャストすることです:' DateTime date =(DateTime)entry ["commit"] ["committer"] ["date"]; ' 。それが私に以前に起こらなかった理由はわかりませんが、明示的に生の文字列が必要な場合のDateParseHandlingオプションについて知っておくと便利です。 –

0

内部の日付としてではなく、文字列として日付探して値を格納Json.Net(それは他の基地のために同じことを行いますデータ型も同様)。したがって、これらの値を操作し始めると、実際にはその値の内部表現(日付型)を処理していて、それを文字列として取得すると、その内部値の文字列変換が返されます。あなたが期待している元の文字列ではありません。

JSのJSONとC#のJson.Netの使用との違いは注目に値するのですが、不幸なIMHOの場合、回避するには追加コードが必要です。

+0

基本的にJson.Netはあなたのように動作します: '' 'date":new Date( "....") '' ' –

関連する問題