Làm cách nào để phân tích JSON để nhận một đối tượng Date trong JavaScript?


117

Tôi có một đoạn JSON sau đây:

\/Date(1293034567877)\/

đó là kết quả của mã .NET này:

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

Bây giờ vấn đề tôi gặp phải là làm thế nào để tạo một đối tượng Date từ điều này trong JavaScript. Tất cả những gì tôi có thể tìm thấy là giải pháp regex đáng kinh ngạc (nhiều lỗi chứa).

Thật khó để tin rằng không có giải pháp tao nhã nào vì đây là tất cả trong JavaScrip, ý tôi là mã JavaScript đang cố đọc JSON (Ký hiệu đối tượng JavaScript) được cho là mã JavaScript và tại thời điểm này, nó hóa ra không phải vì JavaScript không thể làm tốt công việc ở đây

Tôi cũng đã thấy một số giải pháp tệ hại mà tôi không thể thực hiện được (bên cạnh việc bị chỉ ra là mối đe dọa an ninh).

Có thực sự không có cách nào để làm điều đó một cách thanh lịch?

Câu hỏi tương tự không có câu trả lời thực sự:
Cách phân tích định dạng Ngày của JSON JSON bằng GWT


2
Bạn chỉ có thể truyền dấu thời gian cho khách hàng và gọi new Date()nó.
jAndy

Nếu tôi có dấu thời gian thì tôi có thể, nhưng tôi có JSON mà JavaScript dường như không hiểu [sic!]
Piotr Owsiak

Câu trả lời:


51

Không có đại diện JSON tiêu chuẩn của ngày. Bạn nên làm những gì @jAndy đề xuất và không tuần tự hóa một DateTimechút nào; chỉ cần gửi một chuỗi ngày RFC 1123 ToString("r")hoặc một số giây từ Unix-epoch hoặc một cái gì đó khác mà bạn có thể sử dụng trong JavaScript để xây dựng một Date.


3
Cảm ơn tôi đã đi vào một con đường chết, bạn là người đầu tiên chỉ ra rằng JSON không hỗ trợ loại Ngày.
Piotr Owsiak

3
JSON hỗ trợ các số, chuỗi, đối tượng, mảng và các chữ đúng, sai và null. Vì Date không phải là một trong số đó, nên nó là một loại phức tạp nên được lưu trữ dưới dạng một đối tượng, thay vì một chuỗi, vì vậy bạn có thể bao gồm thông tin loại như tên loại trong các thành viên đặc biệt như "$ type" sẽ không bao giờ giải quyết được thành viên đối tượng thực sự. Các thành viên meta như vậy có thể được sử dụng để hồi sinh đối tượng JSON thành đối tượng thời gian chạy được gõ mạnh sau này. Tôi nghĩ rằng việc thực hành gắn một ngày trong một chuỗi là ngu ngốc, bởi vì nó không cần thiết tạo ra các mẫu chuỗi dành riêng và cố gắng khớp chúng trên mỗi chuỗi.
Triynko

4
Hiện tại có một định dạng ngày JSON tiêu chuẩn. tools.ietf.org/html/rfc7493#section-4.3
Bryan Larsen

128

Các JSON.parsechức năng chấp nhận một chức năng DateTime Reviver tùy chọn. Bạn có thể sử dụng một chức năng như thế này:

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

Sau đó gọi

JSON.parse(somejsonstring, dateTimeReviver);

Và ngày của bạn sẽ đi ra ngay.


1
Cũng phát hiện, khá hữu ích.
noup

5
Thực hành mã hóa dữ liệu gõ không nguyên thủy này theo kiểu nguyên thủy (chuỗi) là điên rồ. Mã hóa ngày trong một đối tượng JSON có các thuộc tính có ý nghĩa hoặc thậm chí đi xa hơn, bao gồm thuộc tính "$ type" trong đối tượng JSON để thói quen phân tích cú pháp / giải nén có thể hồi sinh loại một cách thích hợp và thậm chí sử dụng trình chuyển đổi tùy chỉnh nếu bạn muốn đóng gói tất cả thông tin vào một giá trị thuộc tính duy nhất như "ticks" hoặc "ms_since_epoch".
Triynko

7
Tôi đã phải sửa đổi biểu thức chính quy như thế này / \ / Ngày ((-? \ D *)) \ // để nó cũng có thể xử lý các số âm. Các số âm xuất hiện khi bạn có DateTime rất cũ (trước Kỷ nguyên) đã được .NET chuyển đổi thành JSON.
ClearCloud8

@ ClearCloud8: Bạn bỏ lỡ các dấu gạch chéo ngược: / \ / Ngày \ ((-? \ D *) \) \ //
Jerther

1
Tôi chưa bao giờ biết về chức năng này - điều này rất hữu ích!
keldar

50

Câu trả lời này của Roy Tinker tại đây :

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

Như ông nói: Hàm cơ sở lấy ra phần "/ Ngày (" và hàm parseInt lấy số nguyên và bỏ qua ") /" ở cuối. Số kết quả được truyền vào hàm tạo ngày.

Một tùy chọn khác là chỉ cần định dạng đúng thông tin của bạn ở phía ASP để JavaScript có thể dễ dàng đọc nó. Xem xét làm điều này cho ngày của bạn:

DateTime.Now()

Mà sẽ trả về một định dạng như thế này:

7/22/2008 12:11:04 PM

Nếu bạn chuyển cái này vào hàm tạo JavaScript Datenhư thế này:

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

Biến datehiện giữ giá trị này:

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

Đương nhiên, bạn có thể định dạng DateTimeđối tượng này thành bất kỳ loại chuỗi / int nào mà hàm tạo JS Datechấp nhận.


Cảm ơn Treeface, câu trả lời này đã giúp tôi ra một cái gì đó gần đây!
Malice

4
Không bao giờ, bao giờ, dựa vào ngày mặc định <-> định dạng chuyển đổi chuỗi. Sử dụng mili giây kể từ Epoch, nằm trong miền kiểu số, đơn giản và đáng tin cậy hơn nhiều.
Johan Boulé

2
Câu trả lời này trình bày hai giải pháp - giải pháp thứ nhất đúng (parseInt) và giải pháp thứ hai sai, vì vậy không chắc chắn nên upvote hay downvote! Vấn đề chỉ đơn giản là xuất ra dưới dạng chuỗi là ngày có thể dễ dàng lật ngược lại nếu máy chủ ở một quốc gia, ví dụ như Hoa Kỳ và trình duyệt ở một quốc gia khác, ví dụ như Vương quốc Anh.
mike nelson

Câu trả lời đầu tiên cho tôi bất kỳ loại manh mối nào
Nick.McDilyn

Một câu trả lời OK cho đến khi " Cân nhắc làm điều này cho những ngày của bạn ". Đề xuất một định dạng tiêu chuẩn không liên kết giới thiệu các vấn đề phân tích cú pháp và múi giờ phụ thuộc thực hiện không phải là một ý tưởng hay. Định dạng OP là thích hợp hơn (mặc dù không lý tưởng).
RobG

21

nếu bạn sử dụng ngày ISO8601 theo kiểu JavaScript trong JSON, bạn có thể sử dụng ngày này, từ MDN

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

2
Imo đây là câu trả lời tao nhã nhất và nên được chấp nhận.
Giăng

1
Thực sự rất thanh lịch, nhưng điều này không liên quan đến định dạng ngày cụ thể đã được đề cập trong câu hỏi.
vào

@aslop - nếu người dùng không thể chuyển đổi ngày thành / từ ISO, thì JSON là vấn đề ít nhất.
LeeGee

7

Bạn có thể chuyển đổi ngày JSON thành định dạng ngày bình thường trong JavaScript.

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

6

Có chuyện gì với:

new Date(1293034567877);

Điều này trả lại cho tôi "Thứ tư ngày 22 tháng 12 năm 2010 16:16:07 GMT + 0000 (Giờ chuẩn GMT)".

Hay bạn cần lấy số ra json?


3
Điều gì là sai với giải pháp của bạn? Chà, 1293034567877 không phải là JSON tôi có, phải không? Ngoài ra, tôi không cần lấy số JSON, tôi cần lấy ngày ra khỏi JSON. Tôi đang mong đợi một chút từ JavaScript hơn là chỉ có thể làm mọi thứ với regex. Tôi cần mã của tôi để có thể đọc được và không giống như một lời nguyền hoạt hình.
Piotr Owsiak

7
Tôi đổ lỗi cho .NET đã tạo ra một chuỗi tuần tự của một đối tượng ngày ở định dạng kỳ lạ như \/Date(1293034567877)\/. Nếu nó lành mạnh, nó sẽ chỉ xuất thời gian kỷ nguyên và bạn có thể khởi tạo một đối tượng Date với điều đó.
Quentin

2
@treeface: Nếu JSON không phải là JavaScript thì tôi nghĩ rằng các hướng dẫn và sách sẽ bị đổ lỗi cho sự hiểu lầm phổ biến này. Dù sao tôi cũng sẵn sàng sửa chữa, thực sự. Đối với gợi ý của bạn rằng Ngày có thể được biểu diễn dưới dạng Chuỗi, tôi có thể nói rằng mọi thứ đều có thể được biểu diễn dưới dạng Chuỗi, phải không? Nhưng điều này sẽ không làm cho công việc của chúng ta dễ dàng hơn, nhưng vô cùng đau đớn và khủng khiếp. Tôi đoán vấn đề của tôi xuất phát từ thực tế là tôi đã coi JSON là một định dạng tuần tự hóa (được quảng cáo là có ít băng thông hơn và hoạt động tốt hơn với JavaScript so với XML). Hóa ra là không, ít nhất không phải là không đau.
Piotr Owsiak

1
@treeface: Tôi đã google yêu cầu của bạn về JSON và phát hiện ra rằng JSON là JavaScript, thực ra nó là một tập hợp con của JavaScript. Xem RFC # 4627 "Loại phương tiện / ứng dụng json cho Ký hiệu đối tượng JavaScript (JSON)" và tìm kiếm một tuyên bố: "Mục tiêu thiết kế của JSON là để nó tối thiểu, di động, văn bản và một tập hợp con của JavaScript.". Bây giờ khi tôi nghĩ về nó, có vẻ hiển nhiên khi bạn có thể gọi eval () trên JSON.
Piotr Owsiak

1
@David Dorward: Tôi muốn có sự phức tạp thêm vào được triển khai sâu bên trong các thư viện (.NET, Java, Ruby, Python, hoặc ngôn ngữ / nền tảng bạn đang sử dụng) thay vì để lại chi tiết được xử lý bởi lập trình viên. Cũng lưu ý rằng bạn không cần hỗ trợ kiểu dữ liệu boolean và số nguyên trong JSON, bạn chỉ có thể đặt chúng trong chuỗi, phải không? Bạn có thể tưởng tượng sẽ tuyệt vời đến mức nào khi nhận được bất kỳ thứ gì từ JSON không?
Piotr Owsiak

2

Tôi biết đây là một chủ đề rất cũ nhưng tôi muốn đăng bài này để giúp những người gặp phải vấn đề này như tôi đã làm.

nếu bạn không quan tâm đến việc sử dụng tập lệnh của bên thứ 3, bạn có thể sử dụng khoảnh khắc, js Sau đó, bạn có thể sử dụng .format () để định dạng tập lệnh thành bất cứ điều gì bạn muốn.


2

Ngày tháng luôn là cơn ác mộng. Trả lời câu hỏi cũ của bạn, có lẽ đây là cách thanh lịch nhất:

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

Với eval, chúng tôi chuyển đổi chuỗi của chúng tôi thành mã javascript. Sau đó, chúng tôi loại bỏ "/", vào chức năng thay thế là một biểu thức thông thường. Khi chúng tôi bắt đầu với mới, câu của chúng tôi sẽ thực hiện điều này:

new Date(1455418800000)

Bây giờ, một điều tôi bắt đầu sử dụng từ lâu, là các giá trị dài được biểu thị bằng dấu ... tại sao? tốt, nội địa hóa và ngừng suy nghĩ về cách ngày được cấu hình trong mỗi máy chủ hoặc mọi máy khách. Trong thực tế, tôi cũng sử dụng nó trong cơ sở dữ liệu.

Có lẽ là khá muộn cho câu trả lời này, nhưng có thể giúp bất cứ ai mắc kẹt ở đây.


Btw, tiếng Anh của tôi với nhiều năm đang trở nên tồi tệ hơn bao giờ hết ... nhưng tôi đoán tôi đã tự hiểu.
Gabriel Andrés Brancolini

Câu trả lời của bạn hoạt động rất tốt, đã giúp tôi thoát khỏi một mứt. Cảm ơn.
BoredBsee

1

AngularJS không thể phân tích /Date(xxxxxxxxxxxxx)/chuỗi ngày .NET JSON ..

Tôi đã giải quyết vấn đề này bằng cách định dạng ngày thành biểu diễn chuỗi ISO 8601 thay vì đổ Datetrực tiếp đối tượng ...

Đây là một mẫu mã ASP.NET MVC ..

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

Tôi đã thử RFC 1123nhưng nó không hoạt động .. Angular coi đây là chuỗi thay vì Date.

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

0

Tôi đã không sử dụng .Net cho những thứ như thế này. Nếu bạn có thể làm cho nó in ra một cái gì đó như sau đây thì nó sẽ hoạt động.

Lưu ý, trừ khi bạn phân tích chuỗi JSON đó bằng một số phương tiện khác hoặc chỉ mong người dùng có trình duyệt hiện đại với trình phân tích cú pháp JSON tích hợp, bạn cần sử dụng khung công tác JS hoặc JSON2 để phân tích chuỗi JSON được máy chủ đưa ra thành JSON thực vật.

// 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) );

Liên kết Wiki

Các trình duyệt hiện đại, như Firefox 3.5 và Internet Explorer 8, bao gồm các tính năng đặc biệt để phân tích cú pháp JSON. Vì hỗ trợ trình duyệt riêng hiệu quả và an toàn hơn eval (), dự kiến ​​hỗ trợ JSON gốc sẽ được đưa vào tiêu chuẩn ECMAScript tiếp theo. [6]


Liên kết đến tệp JSON2

Ví dụ trực tiếp


Tôi hiểu điều đó, nhưng vấn đề của tôi với loại JSON và Ngày là tôi cần phải thực hiện "Ngày mới (" là một) công việc bổ sung b) bổ sung kiến ​​thức cần truyền đạt tới người tiêu dùng. Tôi thực sự thất vọng khi tìm hiểu cách xử lý vấn đề này và về cơ bản, tôi coi đó là một lỗi trong thông số JSON.
Piotr Owsiak

0

Câu trả lời cho câu hỏi này là, sử dụng nuget để lấy JSON.NET, sau đó sử dụng JsonResultphương thức này trong phương thức của bạn :

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

Trong quan điểm của bạn đơn giản làm điều này trong javascript:

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

Nếu đó là một cuộc gọi 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); });

Khi JSON.parseđã được gọi, bạn có thể đặt ngày JSON vào một new Datethể hiện vì JsonConverttạo một thể hiện thời gian ISO thích hợp


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

Như Callum đã đề cập, đối với tôi, cách tốt nhất là thay đổi phương thức Bộ điều khiển thành chuỗi thay vì JsonResult ".

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

Từ phương pháp ajax bạn có thể làm một cái gì đó như thế này

 $.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

sử dụng chức năng eval chỉ cần loại bỏ dấu gạch chéo về phía trước và phía sau.

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

mang lại Thu 01 tháng 1 năm 1970 00:00:00 GMT-0700 (Giờ chuẩn miền núi Hoa Kỳ)


0

Tôi gặp vấn đề với API bên ngoài cung cấp ngày ở định dạng này, đôi khi ngay cả với thông tin khác biệt UTC như thế nào /Date(123232313131+1000)/. Tôi đã có thể biến Dateđối tượng js bằng mã sau

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
Bạn sẽ không trả về một đối tượng ngày, theo như tôi hiểu mã.
Johan Boulé

-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;
};

// Sử dụng chức năng này

var objDate=parseJsonDate("\/Date(1443812400000)\/");
alert(objDate);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.