JSONを解析してJavaScriptで日付オブジェクトを受け取る方法は?


117

次のJSONがあります。

\/Date(1293034567877)\/

これはこの.NETコードの結果です:

var obj = DateTime.Now;
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
serializer.Serialize(obj).Dump();

今私が直面している問題は、JavaScriptでこれからDateオブジェクトを作成する方法です。私が見つけることができたのは信じられないほどの正規表現ソリューション(多くのバグを含む)でした。

これはすべてJavaScripであるため、エレガントな解決策がないとは信じがたいです。つまり、JavaScriptコードはJavaScriptコードであるはずのJSON(JavaScript Object Notation)を読み取ろうとしているのですが、現時点ではJavaScriptが原因ではないことがわかりましたここで良い仕事をしてください。

また、セキュリティ上の脅威として指摘されている以外に、動作させることができないevalソリューションもいくつか見ました。

エレガントな方法でそれを行う方法は本当にありませんか?

本当の答えのない同様の質問:
GWTでASP.NET JSON日付形式を解析する方法


2
タイムスタンプをクライアントに渡して呼び出すnew Date()だけです。
jAndy

タイムスタンプは
取得

回答:


51

日付の標準JSON表現はありません。@jAndyが提案したことを実行し、a DateTimeをまったくシリアル化しないでください。RFC 1123の日付文字列ToString("r")やUnixからのエポック秒数など、JavaScriptで使用してを構築できるものを送信するだけDateです。


3
デッドパスをたどってくれてありがとう。JSONが日付タイプをサポートしていないことを最初に指摘したのはあなたです。
Piotr Owsiak 2010

3
JSONは、数値、文字列、オブジェクト、配列、およびリテラルtrue、false、nullをサポートしています。Dateはこれらのいずれでもないため、文字列ではなくオブジェクトとして保存する必要がある複雑な型であるため、「$ type」などの特殊なメンバーに型名などの型情報を含めて、実際のオブジェクトのメンバー。そのようなメタメンバーは、JSONオブジェクトを後で強く型付けされたランタイムオブジェクトに復活させるために使用できます。日付を文字列に貼り付けるのはばかげていると思います。予約された文字列パターンを不必要に作成し、すべての文字列でそれらを照合しようとするからです。
Triynko

4
現在、標準のJSON日付形式があります。 tools.ietf.org/html/rfc7493#section-4.3
ブライアンラーセン

128

このJSON.parse関数は、オプションのDateTimeリバイバー関数を受け入れます。次のような関数を使用できます。

dateTimeReviver = function (key, value) {
    var a;
    if (typeof value === 'string') {
        a = /\/Date\((\d*)\)\//.exec(value);
        if (a) {
            return new Date(+a[1]);
        }
    }
    return value;
}

次に電話します

JSON.parse(somejsonstring, dateTimeReviver);

そして、あなたの日付は正しく出てきます。


1
よく見分けられ、非常に便利です。
noup

5
プリミティブではない型付きデータをプリミティブ型(文字列)にエンコードするこの習慣は非常識です。意味のあるプロパティを使用してJSONオブジェクトに日付をエンコードするか、さらに進むには、JSONオブジェクトに「$ type」プロパティを含めて、解析/非直列化ルーチンがタイプを適切に復活させ、すべてをパックしたい場合はカスタムコンバーターを使用することもできます「ティック」や「ms_since_epoch」などの単一のプロパティ値への情報。
Triynko

7
/ \ / Date((-?\ d *))\ //のように正規表現を変更して、負の数も処理できるようにする必要がありました。負の数は、.NETによってJSONに変換された非常に古いDateTime(エポックの前)がある場合に表示されます。
ClearCloud8 2014年

@ ClearCloud8:バックスラッシュを逃します:/ \ / Date \((-?\ d *)\)\ //
Jerther 2014年

1
私はこの機能を知りませんでした-これはとても便利です!
ケルダー2016

50

ここでロイティンカーからのこの答え:

var date = new Date(parseInt(jsonDate.substr(6)));

彼が言うように: substr関数は "/ Date("の部分を取り出し、parseInt関数は整数を取得し、最後の ")/"を無視します。結果の数値は、Dateコンストラクターに渡されます。

別のオプションは、JavaScriptが情報を簡単に読み取れるように、ASP側で情報を適切にフォーマットすることです。あなたの日付のためにこれを行うことを検討してください:

DateTime.Now()

これは次のようなフォーマットを返すはずです:

7/22/2008 12:11:04 PM

これをJavaScriptに渡すと Dateようなコンストラクタに

var date = new Date('7/22/2008 12:11:04 PM');

変数 date次の値が保持されます。

Tue Jul 22 2008 12:11:04 GMT-0700 (Pacific Daylight Time)

当然、このDateTimeオブジェクトを、JS Dateコンストラクターが受け入れる任意の種類の文字列/ intにフォーマットできます。


treefaceのおかげで、この答えは最近何かを助けてくれました!
Malice

4
デフォルトの日付<->文字列変換フォーマットに依存することはありません。数値型ドメインに留まるEpochからのミリ秒の使用は、はるかに単純で信頼性が高くなります。
JohanBoulé12年

2
この回答は2つの解決策を提示します-最初の解決策は正しい(parseInt)であり、2番目の解決策は間違っているため、賛成投票か反対投票かはわかりません!単に文字列として出力する場合の問題は、サーバーが米国などの国にあり、ブラウザが英国など別の国にある場合、日付が逆になりやすいことです。
マイクネルソン2013年

あらゆる種類の手がかりを私に与える最初の答え
Nick.McDermaid

あなたの日付でこれを行うことを検討してください…」までのOK回答。実装に依存する解析とタイムゾーンの問題を導入する非標準形式を提案することは良い考えではありません。OPフォーマットが推奨されます(ただし、理想的ではありません)。
RobG

21

JSONでJavaScriptスタイルのISO8601日付を使用する場合、MDNからこれを使用できます

var jsonDate = (new Date()).toJSON();
var backToDate = new Date(jsonDate);
console.log(jsonDate); //2015-10-26T07:46:36.611Z

2
これは最もエレガントな答えであり、受け入れられるべきものです。
John

1
確かに非常にエレガントですが、これは質問で言及された特定の日付形式とは関係ありません。
asiop 2016

@aslop-ユーザーがISOとの間で日付を変換できない場合は、JSONが最も問題が少ないです。
LeeGee 2018

7

JavaScriptでJSON日付を通常の日付形式に変換できます。

var date = new Date(parseInt(jsonDate.substr(6)));

6

どうしたの:

new Date(1293034567877);

これにより、「2010年12月22日水曜日16:16:07 GMT + 0000(GMT標準時)」が返されます。

または、jsonから番号を取得する必要がありますか?


3
あなたのソリューションの何が問題になっていますか?1293034567877は私が持っているJSONではありませんよね?また、JSONから数値を取得する必要はありません。JSONから日付を取得する必要があります。私は、正規表現ですべてを実行できることだけではなく、JavaScriptに少し期待しています。コードが読みやすく、漫画の呪いのように見えないようにする必要があります。
Piotr Owsiak 2010

7
.NETを、奇妙な形式で日付オブジェクトのシリアル化を生成したことを非難します\/Date(1293034567877)\/。正気だった場合は、エポック時間を出力するだけで、それを使用してDateオブジェクトを初期化できます。
クエンティン

2
@treeface:JSONがJavaScriptでない場合、チュートリアルと本はこの一般的な誤解のせいだと思います。とにかく私は喜んで正直に立ちます。日付を文字列として表すことができるというあなたの提案については、すべてを文字列として表すことができると言えるでしょうか?しかし、これは私たちの仕事を容易にしませんが、ひどく苦痛で地獄です。私の問題は、JSONをシリアル化形式(帯域幅を節約し、XMLよりもJavaScriptでより適切に動作するように宣伝されている)と見なしたという事実に起因すると思います。実際にはそうではありませんが、少なくとも痛みのないものではありません。
Piotr Owsiak 2011年

1
@treeface:JSONに関するあなたの主張をグーグルで調べたところ、JSONはJavaScriptであり、実際にはJavaScriptのサブセットであることがわかりました。RFC#4627「JavaScript Object Notation(JSON)のapplication / json Media Type」を参照して、「JSONの設計目標は、それが最小限で、移植可能で、テキストであり、JavaScriptのサブセットになることでした」というステートメントを探します。今考えてみると、JSONでeval()を呼び出すことができるのは明らかです。
Piotr Owsiak 2011年

1
@David Dorward:プログラマーが処理する詳細を残さずに、ライブラリ(.NET、Java、Ruby、Python、または使用しているあらゆる言語/プラットフォーム)の奥深くに複雑さを実装したい。また、JSONでブール型と整数型のデータをサポートする必要はないことに注意してください。これらを文字列に入れるだけでいいのですよね?それでは、JSONからとにかくどれほどひどいものになるか想像できますか?
Piotr Owsiak 2011年

2

私はこれが非常に古いスレッドであることを知っていますが、私がそうしたようにこれにぶつかった人を助けるためにこれを投稿したいと思います。

サードパーティのスクリプトを使用する必要がない場合は、moment、js を使用できます。次に .format()を使用して、任意の形式にフォーマットできます。


2

日付は常に悪夢です。あなたの古い質問に答えると、おそらくこれは最もエレガントな方法です:

eval(("new " + "/Date(1455418800000)/").replace(/\//g,""))

evalを使用して、文字列をJavaScriptコードに変換します。次に、「/」を削除し、replace関数に正規表現を挿入します。新しいものから始めると、私たちの文はこれを実行します:

new Date(1455418800000)

さて、私がずっと前に使用し始めたことの1つは、ティックで表される長い値です...なぜですか?さて、ローカリゼーションとすべてのサーバーまたはすべてのクライアントで日付がどのように構成されているかについて考えるのをやめます。実際、私もデータベースで使用しています。

おそらくこの答えにはかなり遅れますが、ここで周りの人を助けることができます。


ところで、私の英語の年数はこれまでになく最悪になっています...しかし、私は自分の理解を深めたと思います。
GabrielAndrésBrancolini、2016

あなたの答えはうまくいき、私は込み合いから抜け出しました。ありがとう。
BoredBsee

1

AngularJSは.NET JSON日付/Date(xxxxxxxxxxxxx)/文字列も解析できませんでした。

Dateオブジェクトを直接ダンプするのではなく、ISO 8601文字列表現に日付をフォーマットすることで、この問題を回避しました...

ASP.NET MVCコードのサンプルを次に示します。

return Json(new { 
  date : DateTime.Now.ToString("O") //ISO 8601 Angular understands this format
});

試しましたRFC 1123が動作しません。Angularはこれを日付ではなく文字列として扱います。

return Json(new { 
  date : DateTime.Now.ToString("R") //RFC 1123 Angular won't parse this
});

0

このようなことのために.Netを使用していません。次のようなものを印刷することができた場合は、機能するはずです。

他の方法でそのJSON 文字列を解析している場合や、ユーザーが組み込みのJSONパーサーを備えた最新のブラウザーを使用している場合にのみ、サーバーから出力されたJSON文字列をJSフレームワークまたはJSON2を使用して実際のJSONに解析する必要があることに注意してください。オブジェクト。

// JSON received from server is in string format
var jsonString = '{"date":1251877601000}';

//use JSON2 or some JS library to parse the string
var jsonObject =  JSON.parse( jsonString );

//now you have your date!
alert( new Date(jsonObject.date) );

Wikiリンク

Firefox 3.5やInternet Explorer 8などの最新のブラウザには、JSONを解析するための特別な機能が含まれています。ネイティブブラウザサポートはeval()よりも効率的で安全であるため、ネイティブJSONサポートは次のECMAScript標準に含まれる予定です。[6]


JSON2ファイルへのリンク

実例


わかりましたが、JSONと日付タイプの問題は、「新しい日付()」を明示的に実行する必要があるということです。これがどのように処理されるかを知り、私は本当にがっかりしました。基本的には、JSON仕様の誤りだと考えています。
Piotr Owsiak 2010

0

この質問に対する答えは、nugetを使用してJSON.NETを取得し、JsonResultメソッド内でこれを使用することです。

JsonConvert.SerializeObject(/* JSON OBJECT TO SEND TO VIEW */);

あなたのビューの中でこれを簡単にしてくださいjavascript

JSON.parse(/* Converted JSON object */)

ajax呼び出しの場合:

var request = $.ajax({ url: "@Url.Action("SomeAjaxAction", "SomeController")", dataType: "json"});
request.done(function (data, result) { var safe = JSON.parse(data); var date = new Date(safe.date); });

JSON.parse呼び出されたら、適切なISO時間インスタンスを作成するnew Dateため、JSON日付をインスタンスに入れることができJsonConvertます


0
function parseJsonDate(jsonDate) {

    var fullDate = new Date(parseInt(jsonDate.substr(6)));
    var twoDigitMonth = (fullDate.getMonth() + 1) + ""; if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;

    var twoDigitDate = fullDate.getDate() + ""; if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
    var currentDate = twoDigitMonth + "/" + twoDigitDate + "/" + fullDate.getFullYear();

    return currentDate;
};

0

Callumが述べたように、私にとっては、コントローラーのメソッドをJsonResultではなくstringに変更するのが最善の方法です。

public string GetValues()
{
  MyObject.DateFrom = DateTime.Now;
  return JsonConvert.SerializeObject(MyObject);
}

ajaxメソッドから、あなたはこのようなことをすることができます

 $.ajax({
 url: "/MyController/GetValues",
 type: "post",
 success: function (data) {
 var validData = JSON.parse(data);
//if you are using datepicker and you want set a format
$("#DateFrom").val($.datepicker.formatDate("dd/mm/yy", new Date(validData.DateFrom)));                                      
// if you want the date as returned
$("#DateFrom").val(new Date(validData.DateFrom))
}
});

0

eval関数を使用するには、前後のスラッシュを削除するだけです。

var date1 = "/Date(25200000)/"
eval("new " + date1.substring(1, date1.length - 1));

1970年1月1日00:00:00 GMT-0700(米国山岳標準時)


0

この形式で日付を提供する外部APIで問題が発生しました/Date(123232313131+1000)/。私はそれDateを次のコードでjs オブジェクトに変えることができました

var val = '/Date(123232311-1000)/';
var pattern = /^\/Date\([0-9]+((\+|\-)[0-9]+)?\)\/$/;
var date = null;

// Check that the value matches /Date(123232311-1000)/ format
if (pattern.test(val)) {
  var number = val.replace('/Date(', '',).replace(')/', '');
  if (number.indexOf('+') >= 0) {
    var split = number.split('+');
    number = parseInt(split[0]) + parseInt(split[1]);
  } else if (number.indexOf('-') >= 0) {
    var split = number.split('-');
    number = parseInt(split[0]) - parseInt(split[1]);
  } else {
    number = parseInt(number);
    date = new Date(number);
  }
}

-1
//
// formats a .net date into a javascript compatible date
//
function FormatJsonDate(jsonDt) 
{              
    var MIN_DATE = -62135578800000; // const

    var date = new Date(parseInt(jsonDt.substr(6, jsonDt.length-8)));                                                       
    return date.toString() == new Date(MIN_DATE).toString() ? "" : (date.getMonth() + 1) + "\\" + date.getDate() + "\\" + date.getFullYear(); 
}

2
私がコードを理解している限り、あなたは日付オブジェクトを返していません。
JohanBoulé12年

-1
function parseJsonDate(jsonDate) {

    var fullDate = new Date(parseInt(jsonDate.substr(6)));
    var twoDigitMonth = (fullDate.getMonth() + 1) + ""; if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;

    var twoDigitDate = fullDate.getDate() + ""; if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
    var currentDate = twoDigitMonth + "/" + twoDigitDate + "/" + fullDate.getFullYear();

    return currentDate;
};

//この関数を使用します

var objDate=parseJsonDate("\/Date(1443812400000)\/");
alert(objDate);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.