2013-01-23 13 views
9

javascriptの日付を持つjsonオブジェクトを逆シリアル化しようとしています。オブジェクトに対してJSON.stringifyが呼び出されると、日付は日付に戻されて正しく逆シリアル化されない文字列にシリアル化されます。私は、クロム、IE、およびFFのネイティブブラウザ実装とjqueryを使用してオブジェクトを逆シリアル化しようとしました。両方ともいくつかの結果が得られます。スニペットは次のとおりです。Javascript JSON日付逆シリアル化

objDeser.Dateを文字列ではなくjs日付にします。あなたはここで実際にこの問題を見ることができます:http://jsbin.com/unijud/24/edit。 Javascriptオブジェクトを構築するときに日付を正しく非直列化できるjsライブラリはありますか?

答えて

5

のために一緒に投げるだろう、私は@LastCoderアドバイスを取り、簡単な実装を書いたものです。それは私が望んでいたことをしているようだ。

var jsonDates = { 
    dtrx2: /\d{4}-\d{2}-\d{2}/, 
    parse: function(obj){ 
     var parsedObj = JSON.parse(obj); 
     return this.parseDates(parsedObj); 
    }, 
    parseDates: function(obj){ 
    // iterate properties 
    for(pName in obj){ 

     // make sure the property is 'truthy' 
     if (obj[pName]){ 
     var value = obj[pName]; 
     // determine if the property is an array 
     if (Array.isArray(value)){ 
      for(var ii = 0; ii < value.length; ii++){ 
      this.parseDates(value[ii]); 
      } 
     } 
     // determine if the property is an object 
     else if (typeof(value) == "object"){ 
      this.parseDates(value); 
     } 
     // determine if the property is a string containing a date 
     else if (typeof(value) == "string" && this.dtrx2.test(value)){ 
      // parse and replace 
      obj[pName] = new Date(obj[pName]); 
     } 
     } 
    } 

    return obj; 
    } 
}; 

ライブの例はjsbinです。参考資料はgistです。

3

JSON仕様には日付の特殊な書式設定は含まれていません。このように、文字列としてシリアル化されることもあります。言語によってサポートされている場合は、Dateオブジェクトとして扱う必要があることを示す特別なマーキングが付いていることがあります。そのため、ほとんどの(すべての)ブラウザ固有のJSONパーサーは、Dateオブジェクトを適切にラウンドトリップできません。

これに役立ついくつかの良いライブラリがあります。私はMomentJSとよく似ていますが、過去にはdatejsも使用しています。オブジェクトを繰り返し処理し、適切なフィールドを解析した後、Dateオブジェクトに変換するだけで済みます。

JSON形式は、JavaScriptオブジェクトのリテラル表記よりもはるかに制限されています。

+0

ありがとうございました。これらのライブラリは日付に機能を追加するようですが、jsonパーサーを拡張/実装するようには見えません。 – mdeangelo272

0

必要なすべての日付関数をString.prototypeに手動で追加することができます。

String.prototype.getYear = function() { 
    return Date.parse(this).getYear(); 
}; 
var obj = {date: new Date()}; 
var dtObj = JSON.parse(JSON.stringify(obj)); 
console.log(dtObj.date.getYear()); 

それとも、JSON.parseをオーバーライドして、タイムスタンプの正規表現にマッチして、Dateオブジェクトに変換した文字列を探して、結果オブジェクトを介してループを持つことができます。

var JSON_parse = JSON.parse; 
JSON.parse = function(str) { 
    var res = JSON_parse(str); 
    findAndConvertStringsToDates(res); 
    return res; 
} 

EDITは、ここで私は、実装

(function() { 
    var jsonParse = JSON.parse; 
    var reDate = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/i; 
    function jsonDate(obj) { 
     var type = typeof(obj); 
     if(type == 'object') { 
      for(var p in obj) 
       if(obj.hasOwnProperty(p)) 
        obj[p] = jsonDate(obj[p]); 
      return obj; 
     } else if(type == 'string' && reDate.test(obj)) { 
      return new Date(obj); 
     } 
     return obj; 
    } 
    JSON.parse = function(str) { return jsonDate(jsonParse(str)); } 
})(); 
/* 
* Tests 
*/ 
var dt = JSON.parse(JSON.stringify({date: new Date()})); 
console.log(typeof(dt.date)); 
console.log(JSON.parse(JSON.stringify(null))); 
console.log(JSON.parse(JSON.stringify(123))); 
console.log(JSON.parse(JSON.stringify("test"))); 
console.log(JSON.parse(JSON.stringify(new Date()))); 
console.log(JSON.parse(JSON.stringify([1,new Date(),2]))); 
console.log(JSON.parse(JSON.stringify({d: new Date(), d2: {d3: new Date(), d4: [0,new Date(),4]}}))); 
+0

オプション2は本質的に私が後にしているものです。私は、findAndConvertStringsToDates機能を実装したライブラリを見つけることを望んでいました。私はかなりjsの達人ではなく、これを自分で実装する必要はないと考えていました。 – mdeangelo272

+0

@ mdeangelo272 - 私は実行可能なソリューションで編集しました。非常に古いブラウザには問題があるかもしれませんが、20行未満のコードで作業するのはあまりありません。 –

+1

この回答を将来見つけた人にとっては、これは非常に悪い考えです。これはJSONグローバルを変更するので、JSONグローバルを使用するページ上のライブラリは、非標準的な振る舞いをするこのサルパッチバージョンを取得します。この動作が必要な場合は、グローバルJSONオブジェクトに追加するのではなく、別の関数を使用してください。 – bcherny

7

JSON.parseには、ほとんど知られていない第2パラメータ「reviver」機能があります。これは正確にこの目的のために使用されます:最初の解析中に日付文字列をDateオブジェクト(または、仮に、文字列から変換したい他の種類のオブジェクト)に復活させる。

があり、この程度SO postをだし、ここでの実装例とプロパティは夫婦共通の日付のエンコーディングのチェックを行います機能が含まblog postです(ISO &をその奇妙な.NETのAJAX形式)、Dateに解析する前に。ここで

はそのブログ記事からの重要な機能は、FWIWです:

// JSON date deserializer 
// use as the second, 'reviver' argument to JSON.parse(); 

if (window.JSON && !window.JSON.dateParser) { 
    var reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/; 
    var reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/; 

    JSON.dateParser = function (key, value) { 
     // first, just make sure the property is a string: 
     if (typeof value === 'string') { 
      // then, use regex to see if it's an ISO-formatted string 
      var a = reISO.exec(value); 
      if (a) { 
       // if so, Date() can parse it: 
       return new Date(value); 
      } 
      // otherwise, see if it's a wacky Microsoft-format string: 
      a = reMsAjax.exec(value); 
      if (a) { 
       // and perform some jujitsu to make use of it: 
       var b = a[1].split(/[-+,.]/); 
       return new Date(b[0] ? +b[0] : 0 - +b[1]); 
      } 
      // here, you could insert any additional tests and parse instructions you like, for other date syntaxes... 
     } 
     // important: you need to return any values you're not parsing, or they die... 
     return value; 
    }; 
} 

// use: JSON.parse(json,JSON.dateParser); 

(ISO 8601の日付のための適切な正規表現についてlots of opinionsがありますYMMVは。また、関数をグローバルJSONオブジェクトにパンチする特別な理由はありません。どこにでも好きな場所に保管/参照することができます。 )

+0

より良いISO日付の正規表現:/^\ d {4} - (0 [1-9] | 1 [0-2]) - ([12] \ d | 0 [1-9] | 3 [01]) \ [0-5] \ d | 24 \:00)(\:[0-5] \ d([\。 ([0-5] \ d)?)?)?)[?]() ?$/' – asdfasdfads

0

JavaScriptを使用して日付を表すために、JSONは日付を文字列としてエンコードする特定の文字列形式であるISO 8601を使用しています。私が最後にチェックしたときに、日付形式の外観の公式な標準はありません。主要なブラウザは、ISO 8601をJSON Dateエンコーディング形式として使用します。

したがって、日付はISO 8601文字列としてエンコードされ、JSONがシリアル化されてデシリアライズされるときに通常の文字列と同じように使用されます。

言い換えれば、ISO日付はJavaScript Dateコンストラクタを使用してJavaScript日付に変換することができます.JavaScript Dateコンストラクタは、さまざまな入力を受け付けて日付を作成します.ISO 8601の1つです。

取得今日の日付:

var curDate = new Date(); 
document.write(curDate); //Mon Feb 01 2016 12:57:12 GMT-0600 (Central Standard Time) 

文字列にそれを解析します。

var dateStr = JSON.parse(JSON.stringify(curDate)); 
document.write(dateStr);//2016-02-01T18:59:35.375Z 

そして、コンストラクタを使用して、バックjavascriptの日付に変換します

var date = new Date(curDate); 
document.write(date); //Mon Feb 01 2016 12:59:35 GMT-0600 (Central Standard Time) 
関連する問題