18

JavaScript の日付を含む json オブジェクトを逆シリアル化しようとしています。オブジェクトで JSON.stringify が呼び出されると、日付は文字列にシリアル化されますが、日付に正しく逆シリアル化されません。クロム、IE、および FF を使用したネイティブ ブラウザー実装と jquery の両方を使用して、オブジェクトを逆シリアル化しようとしました。どちらもある程度の結果をもたらします。スニペットは次のとおりです。

var obj = {Date: new Date()};
var objSer = JSON.stringify(obj);
var objDeser = JSON.parse(objSer);
var objJqDeser = $.parseJSON(objSer);

function getYear(value){
  try{
     return value.getYear();
  }
  catch(err){
    return err;
  }
}

$("#orig").text("Orig Year: " + getYear(obj.Date));
$("#deser").text("Deser Year: " + getYear(objDeser.Date));
$("#jqDeser").text("JqDeser Year: " + getYear(objJqDeser.Date));

objDeser.Date を文字列ではなく js の日付にしたい。この問題の実際の動作は、http: //jsbin.com/unijud/24/editで確認できます。javascriptオブジェクトを構築するときに日付を適切に逆シリアル化できるjsライブラリはありますか?

4

6 に答える 6

12

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

これについてはSO の投稿あり、実装例と、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 日付の適切な正規表現については多くの意見があります。YMMV。また、関数をグローバル JSON オブジェクトに打ち込む特別な理由はありません。好きな場所に保存/参照できます。)

于 2014-05-16T01:30:03.333 に答える
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で入手できます。参考資料は要点で入手できます。

于 2013-01-24T00:22:37.250 に答える
3

JSON 仕様には、日付の特別な書式設定は含まれていません。そのため、文字列としてシリアル化されることが多く、言語でサポートされている場合は Date オブジェクトとして扱われるべきであることを示す特別なマークが付けられることがあります。そのため、ほとんどの (すべて?) ブラウザーネイティブの JSON パーサーは、Date オブジェクトを適切にラウンドトリップできません。

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

JSON 形式は JavaScript のオブジェクト リテラル表記よりもはるかに制限が厳しいことを覚えておくと役に立ちます。

于 2013-01-23T20:43:20.743 に答える
0

必要なすべての Date 関数を手動で 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;
} 

編集これが私が実装のために一緒に投げるものです

(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]}})));
于 2013-01-23T20:57:42.983 に答える