Bagaimana cara mengurai JSON untuk menerima objek Date di JavaScript?

117

Saya memiliki bagian JSON berikut:

\/Date(1293034567877)\/

yang merupakan hasil dari kode .NET ini:

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

Sekarang masalah yang saya hadapi adalah bagaimana membuat objek Tanggal dari ini di JavaScript. Yang bisa saya temukan hanyalah solusi regex yang luar biasa (banyak mengandung bug).

Sulit dipercaya tidak ada solusi elegan karena ini semua ada di JavaScrip, maksud saya kode JavaScript mencoba membaca JSON (JavaScript Object Notation) yang seharusnya merupakan kode JavaScript dan saat ini ternyata bukan penyebab JavaScript tidak bisa. lakukan pekerjaan dengan baik di sini.

Saya juga telah melihat beberapa solusi eval yang saya tidak dapat berfungsi (selain ditunjukkan sebagai ancaman keamanan).

Apakah benar-benar tidak ada cara untuk melakukannya dengan cara yang elegan?

Pertanyaan serupa tanpa jawaban nyata:
Bagaimana mengurai format Tanggal JSON ASP.NET dengan GWT

Piotr Owsiak
sumber
2
Anda bisa meneruskan stempel waktu ke klien dan memanggilnya new Date().
jAndy
Jika saya memiliki stempel waktu, saya bisa, tetapi saya memiliki JSON yang JavaScript tampaknya tidak mengerti [sic!]
Piotr Owsiak

Jawaban:

51

Tidak ada representasi tanggal JSON standar. Anda harus melakukan apa yang disarankan @jAndy dan tidak membuat serial DateTimesama sekali; kirimkan saja string tanggal RFC 1123 ToString("r")atau nomor detik-dari-Unix-epoch, atau sesuatu yang lain yang dapat Anda gunakan di JavaScript untuk membuat file Date.

Yakub
sumber
3
Terima kasih saya turun jalan mati, Anda adalah orang pertama yang menunjukkan bahwa JSON tidak mendukung tipe Tanggal.
Piotr Owsiak
3
JSON mendukung angka, string, objek, array, dan literal true, false, dan null. Karena Date bukan salah satunya, ini adalah tipe kompleks yang harus disimpan sebagai objek, bukan sebagai string, sehingga Anda dapat menyertakan informasi tipe seperti nama tipe dalam anggota khusus seperti "$ type" yang tidak akan pernah diselesaikan menjadi anggota objek nyata. Anggota meta tersebut dapat digunakan untuk menghidupkan kembali objek JSON ke objek runtime yang diketik dengan kuat nanti. Saya pikir praktik menempelkan tanggal dalam sebuah string itu bodoh, karena itu tidak perlu membuat pola string yang dicadangkan dan mencoba mencocokkannya di setiap string.
Triynko
4
Sekarang ada format tanggal JSON standar. tools.ietf.org/html/rfc7493#section-4.3
Bryan Larsen
128

The JSON.parseFungsi menerima fungsi DateTime minuman keras opsional. Anda dapat menggunakan fungsi seperti ini:

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

Kemudian panggil

JSON.parse(somejsonstring, dateTimeReviver);

Dan tanggal Anda akan keluar dengan benar.

Tim
sumber
1
Terlihat bagus, cukup berguna.
noup
5
Praktik encoding data jenis non-primitif dalam jenis primitif (string) ini tidak masuk akal. Enkode tanggal dalam objek JSON dengan properti yang berarti, atau lebih jauh lagi, sertakan properti "$ type" di objek JSON sehingga rutinitas parse / deserialize dapat menghidupkan kembali tipe dengan tepat dan bahkan menggunakan konverter kustom jika Anda ingin mengemas semuanya informasi menjadi satu nilai properti seperti "ticks" atau "ms_since_epoch".
Triynko
7
Saya harus memodifikasi regex seperti ini / \ / Date ((-? \ D *)) \ // sehingga dapat menangani angka negatif juga. Angka negatif muncul ketika Anda memiliki DateTime yang sangat lama (sebelum Epoch) yang diubah oleh .NET menjadi JSON.
ClearCloud8
@ ClearCloud8: Anda melewatkan garis miring ke belakang: / \ / Tanggal \ ((-? \ D *) \) \ //
Jerther
1
Saya tidak pernah tahu tentang fungsi ini - ini sangat berguna!
keldar
50

Jawaban dari Roy Tinker ini :

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

Seperti yang dia katakan: Fungsi substr mengambil bagian "/ Date (", dan fungsi parseInt mendapatkan integer dan mengabaikan ") /" di akhir. Nomor yang dihasilkan diteruskan ke konstruktor Tanggal.

Pilihan lainnya adalah dengan memformat informasi Anda dengan benar di sisi ASP sehingga JavaScript dapat dengan mudah membacanya. Pertimbangkan melakukan ini untuk kencan Anda:

DateTime.Now()

Yang seharusnya mengembalikan format seperti ini:

7/22/2008 12:11:04 PM

Jika Anda meneruskan ini ke Datekonstruktor JavaScript seperti ini:

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

Variabel datesekarang memegang nilai ini:

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

Biasanya, Anda dapat memformat DateTimeobjek ini ke dalam jenis string / int apa pun yang Datediterima oleh konstruktor JS .

permukaan pohon
sumber
Terima kasih treeface, jawaban ini membantu saya dengan sesuatu baru-baru ini!
Malice
4
Jangan pernah, mengandalkan tanggal default <-> format konversi string. Menggunakan milidetik sejak Epoch, yang tetap dalam domain tipe numerik, jauh lebih sederhana dan dapat diandalkan.
Johan Boulé
2
Jawaban ini menyajikan dua solusi - yang pertama benar (parseInt) dan yang kedua salah, jadi tidak yakin apakah akan memberi suara positif atau negatif! Masalah dengan hanya mengeluarkan sebagai string adalah tanggal dapat dengan mudah membalik ke belakang jika server berada di satu negara misalnya AS dan browser di negara lain misalnya Inggris.
mike nelson
Jawaban pertama yang memberi saya petunjuk apa pun
Nick.McDermaid
Jawaban OK sampai " Pertimbangkan melakukan ini untuk kencan Anda… ". Menyarankan format non-standar yang memperkenalkan masalah penguraian dan zona waktu yang bergantung pada implementasi bukanlah ide yang baik. Format OP lebih disukai (meskipun tidak ideal).
RobG
21

jika Anda menggunakan tanggal ISO8601 gaya JavaScript di JSON, Anda dapat menggunakan ini, dari MDN

var jsonDate = (new Date()).toJSON();
var backToDate = new Date(jsonDate);
console.log(jsonDate); //2015-10-26T07:46:36.611Z
LeeGee
sumber
2
imo ini adalah jawaban yang paling elegan dan harus yang diterima.
Yohanes
1
Memang sangat elegan, tetapi ini tidak terkait dengan format tanggal tertentu yang disebutkan dalam pertanyaan.
asiop
@aslop - jika pengguna tidak dapat mengonversi tanggal ke / dari ISO, maka JSON adalah masalah terkecil.
LeeGee
7

Anda dapat mengubah Tanggal JSON ke format tanggal normal dalam JavaScript.

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

Ada apa dengan:

new Date(1293034567877);

Ini mengembalikan untuk saya "Rabu 22 Des 2010 16:16:07 GMT + 0000 (Waktu Standar GMT)".

Atau apakah Anda perlu mengeluarkan nomornya dari json?

Psytronic
sumber
3
Apa yang salah dengan solusi Anda? Jadi 1293034567877 bukanlah JSON yang saya miliki, bukan? Juga saya tidak perlu mengeluarkan nomor dari JSON, saya perlu mendapatkan Tanggal keluar dari JSON. Saya mengharapkan sedikit lebih banyak dari JavaScript daripada hanya bisa melakukan semuanya dengan regex. Saya perlu kode saya agar dapat dibaca dan tidak terlihat seperti kutukan kartun.
Piotr Owsiak
7
Saya akan menyalahkan .NET karena menghasilkan serialisasi objek tanggal dalam format seaneh \/Date(1293034567877)\/. Jika waras, itu hanya akan mengeluarkan waktu epoch dan Anda dapat menginisialisasi objek Date dengan itu.
Quentin
2
@treeface: Jika JSON bukan JavaScript, maka saya pikir tutorial dan buku harus disalahkan atas kesalahpahaman umum ini. Pokoknya saya dengan senang hati dikoreksi, kok. Adapun saran Anda bahwa Tanggal dapat direpresentasikan sebagai String Saya dapat mengatakan bahwa semuanya dapat direpresentasikan sebagai String, bukan? Tapi ini tidak akan membuat pekerjaan kita lebih mudah, tapi sangat menyakitkan dan menyakitkan. Saya kira masalah saya berasal dari fakta bahwa saya menganggap JSON sebagai format serialisasi (diiklankan untuk mengambil lebih sedikit bandwidth dan bekerja lebih baik dengan JavaScript daripada XML). Ternyata tidak, setidaknya bukan yang tidak menyakitkan.
Piotr Owsiak
1
@treeface: Saya melakukan klaim Google tentang JSON dan menemukan bahwa JSON adalah JavaScript, sebenarnya itu adalah bagian dari JavaScript. Lihat RFC # 4627 "The application / json Media Type for JavaScript Object Notation (JSON)" dan cari pernyataan: "Sasaran desain JSON adalah untuk menjadi minimal, portabel, tekstual, dan subset JavaScript.". Sekarang ketika saya memikirkannya, tampaknya jelas karena Anda dapat memanggil eval () di JSON.
Piotr Owsiak
1
@ David Dorward: Saya lebih suka menambahkan kompleksitas diimplementasikan jauh di dalam perpustakaan (baik .NET, Java, Ruby, Python, atau semua bahasa / platform yang Anda gunakan) daripada membiarkan detailnya ditangani oleh programmer. Perhatikan juga bahwa Anda tidak memerlukan dukungan tipe data boolean dan integer di JSON, Anda cukup meletakkannya dalam string, bukan? Dapatkah Anda membayangkan betapa buruknya mendapatkan anythong dari JSON?
Piotr Owsiak
2

Saya tahu ini adalah utas yang sangat lama tetapi saya ingin memposting ini untuk membantu mereka yang mengalami ini seperti yang saya lakukan.

jika Anda tidak peduli tentang penggunaan skrip pihak ketiga, Anda dapat menggunakan moment, js. Kemudian Anda dapat menggunakan .format () untuk memformatnya menjadi apa pun yang Anda inginkan.

Eman
sumber
2

Kencan selalu menjadi mimpi buruk. Menjawab pertanyaan lama Anda, mungkin ini cara paling elegan:

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

Dengan eval kita mengubah string kita menjadi kode javascript. Kemudian kami menghapus "/", ke dalam fungsi ganti adalah ekspresi reguler. Saat kita mulai dengan yang baru maka kalimat kita akan mengeksekusi ini:

new Date(1455418800000)

Sekarang, satu hal yang saya mulai gunakan sejak lama, adalah nilai panjang yang ditunjukkan dengan tanda centang ... mengapa? baik, lokalisasi dan berhenti memikirkan bagaimana tanggal dikonfigurasi di setiap server atau setiap klien. Sebenarnya, saya juga menggunakannya di database.

Mungkin agak terlambat untuk jawaban ini, tetapi dapat membantu siapa pun di sekitar sini.

Gabriel Andrés Brancolini
sumber
Btw, bahasa Inggris saya dengan tahun-tahun semakin buruk dari sebelumnya ... tapi saya rasa saya membuat diri saya mengerti.
Gabriel Andrés Brancolini
Jawaban Anda berfungsi dengan baik, membantu saya keluar dari kemacetan. Terima kasih.
BoredLihat
1

AngularJS juga tidak dapat mengurai /Date(xxxxxxxxxxxxx)/string tanggal .NET JSON ..

Saya juga melangkahi masalah ini dengan memformat tanggal ke representasi string ISO 8601 alih-alih membuang Dateobjek secara langsung ...

Berikut adalah contoh kode ASP.NET MVC ..

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

Saya mencoba RFC 1123tetapi tidak berhasil .. Angular memperlakukan ini sebagai string, bukan Date.

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

Saya belum menggunakan .Net untuk hal-hal seperti ini. Jika Anda bisa membuatnya untuk mencetak sesuatu seperti berikut ini seharusnya berfungsi.

Catatan, kecuali Anda mengurai string JSON itu dengan cara lain atau hanya mengharapkan pengguna memiliki browser modern dengan parser JSON bawaan, Anda perlu menggunakan kerangka kerja JS atau JSON2 untuk mengurai string JSON yang dikeluarkan oleh server menjadi JSON nyata obyek.

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

Tautan Wiki

Browser modern, seperti Firefox 3.5 dan Internet Explorer 8, menyertakan fitur khusus untuk mengurai JSON. Karena dukungan browser asli lebih efisien dan aman daripada eval (), diharapkan dukungan JSON asli akan disertakan dalam standar ECMAScript berikutnya. [6]


Tautkan ke file JSON2

Contoh Langsung

subhaze
sumber
Saya mengerti, tetapi masalah saya dengan JSON dan tipe Tanggal adalah bahwa saya perlu secara eksplisit melakukan "Tanggal baru (" yang merupakan) pekerjaan tambahan b) pengetahuan tambahan yang perlu dikomunikasikan kepada konsumen. Saya sangat kecewa mengetahui bagaimana ini ditangani dan pada dasarnya saya menganggapnya sebagai kesalahan dalam spesifikasi JSON.
Piotr Owsiak
0

Jawaban untuk pertanyaan ini adalah, gunakan nuget untuk mendapatkan JSON.NET lalu gunakan ini di dalam JsonResultmetode Anda :

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

di dalam tampilan Anda, lakukan ini di javascript:

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

Jika itu panggilan 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); });

Setelah JSON.parsedipanggil, Anda dapat memasukkan tanggal JSON ke dalam new Dateinstance karena JsonConvertmembuat instance waktu ISO yang tepat

Callum Linington
sumber
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;
};
Muzafar
sumber
0

Seperti yang disebutkan Callum, bagi saya, cara terbaik adalah mengubah metode Controller menjadi string, bukan JsonResult ".

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

Dari metode ajax Anda bisa melakukan sesuatu seperti ini

 $.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))
}
});
onixpam
sumber
0

menggunakan fungsi eval bekerja hanya harus menghilangkan garis miring di depan dan belakang.

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

hasil Kam 01 Jan 1970 00:00:00 GMT-0700 (Waktu Standar Pegunungan AS)

vernmic
sumber
0

Saya mengalami masalah dengan API eksternal yang memberikan tanggal dalam format ini, beberapa kali bahkan dengan info perbedaan UTC seperti /Date(123232313131+1000)/. Saya bisa mengubahnya menjadi Dateobjek js dengan kode berikut

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);
  }
}
Martin Vich
sumber
-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(); 
}
sunil
sumber
2
Anda tidak mengembalikan objek tanggal, sejauh yang saya mengerti kodenya.
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;
};

// Gunakan fungsi ini

var objDate=parseJsonDate("\/Date(1443812400000)\/");
alert(objDate);
Muzafar Hasan
sumber