Comprendre le Problème de Sérialisation des Dates en JSON
Le standard JSON ne prend pas nativement en charge les types de date et d'heure. Lorsqu'une application backend (comme ASP.NET) sérialise un objet DateTime avec le sérialiseur par défaut (JavaScriptSerializer), le résultat est une chaîne de caractères au format /Date(timestamp)/. Par exemple, /Date(1391141532000)/ représente le nombre de millisecondes écoulées depuis le 1er janvier 1970 (Epoch UTC).
Pour afficher ces données de manière lisible côté client, plusieurs approches existent, que ce soit en transformant les données avant la sérialisation ou en les parsant côté JavaScript.
Rappel sur l'Objet Date en JavaScript
En JavaScript, la gestion du temps repose sur l'objet Date, qui calcule le temps en millisecondes depuis le 1er janvier 1970 00:00:00 UTC. Pour instancier une date à partir d'un timestamp UNIX (en millisecondes), on utilise le constructeur :
const monTimestamp = 1391141532000;
const maDate = new Date(monTimestamp);
Il est crucial de noter que les mois en JavaScript sont indexés de 0 à 11. De plus, les méthodes comme toISOString() ou toLocaleDateString() permettent de formater l'objet pour l'affichage.
Solution 1 : Parsing Côté Client avec JavaScript et Regex
La méthode la plus directe consiste à intercepter la réponse JSON côté frontend, à extraire le timestamp numérique via une expression régulière, puis à créer un objet Date.
Voici une implémentation moderne utilisant jQuery pour récupérer les données et une fonction d'extraction robuste :
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
$.getJSON('/api/employes', function(data) {
$.each(data, function(index, employe) {
const dateEmbauche = extraireDateJSON(employe.DateEmbauche);
$('#listeEmployes').append(
`<li>${employe.Nom} - Embauché le : ${dateEmbauche.toLocaleDateString('fr-FR')}</li>`
);
});
});
});
function extraireDateJSON(chaineDate) {
// Expression régulière pour capturer les millisecondes et le fuseau horaire optionnel
const regex = /\/Date\((\d+)([+-]\d{4})?\)\//;
const correspondance = regex.exec(chaineDate);
if (correspondance) {
const millisecondes = parseInt(correspondance[1], 10);
return new Date(millisecondes);
}
// Fallback si le format n'est pas reconnu
return new Date(chaineDate);
}
</script>
Cette approche est efficaec car elle ne nécessite aucune modification du code backend. L'expression régulière gère également les décalages horaires (comme +0800) souvent inclus par certains sérialiseurs.
Solution 2 : Conversion Côté Serveur avec LINQ (C#)
Si vous préférez envoyer directement des chaînes de caractères formatées, vous pouvez projeter vos objets C# avant la sérialisation. Cela réduit la charge de traitement côté client.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
public class Employe
{
public string Nom { get; set; }
public DateTime DateEmbauche { get; set; }
}
public class GestionnaireApi : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
var listeEmployes = new List<Employe>
{
new Employe { Nom = "Alice", DateEmbauche = new DateTime(2020, 5, 15, 9, 0, 0) },
new Employe { Nom = "Bob", DateEmbauche = new DateTime(2021, 8, 22, 14, 30, 0) }
};
// Projection LINQ pour formater la date en chaîne de caractères
var resultatFormate = listeEmployes.Select(e => new
{
e.Nom,
DateEmbauche = e.DateEmbauche.ToString("yyyy-MM-dd HH:mm:ss")
}).ToList();
var serializeur = new JavaScriptSerializer();
context.Response.Write(serializeur.Serialize(resultatFormate));
}
public bool IsReusable => false;
}
Avec cette méthode, le JSON reçu par le client contiendra directement "DateEmbauche": "2020-05-15 09:00:00", éliminant le besoin de parsing complexe en JavaScript.
Solution 3 : Utilisation de Newtonsoft.Json (Json.NET) en ASP.NET MVC
Dans un environnement ASP.NET MVC, le sérialiseur par défaut (JsonResult) utilise JavaScriptSerializer. Pour contrôler finement le format des dates (comme le format ISO 8601), il est recommandé d'utiliser la bibliothèque Newtonsoft.Json (Json.NET) et de créer un ActionResult personnalisé.
using System;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace MonApplication.Web.Infrastructure
{
public class ResultatJsonPersonnalise : JsonResult
{
public string FormatDate { get; set; }
public ResultatJsonPersonnalise(object donnees, string formatDate = "yyyy-MM-ddTHH:mm:ss")
{
base.Data = donnees;
base.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
this.FormatDate = formatDate;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null) throw new ArgumentNullException(nameof(context));
var reponse = context.HttpContext.Response;
reponse.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType;
if (this.Data != null)
{
var convertisseurDate = new IsoDateTimeConverter
{
DateTimeFormat = this.FormatDate
};
var jsonSerialize = JsonConvert.SerializeObject(this.Data, convertisseurDate);
reponse.Write(jsonSerialize);
}
}
}
}
Dans votre contrôleur, vous pouvez maintenant utiliser cette classe personnalisée :
public class EmployeController : Controller
{
public ActionResult ObtenirEmployes()
{
var employes = new
{
Nom = "Alice",
DateEmbauche = DateTime.Now
};
// Retourne la date au format ISO 8601 ou personnalisé
return new ResultatJsonPersonnalise(employes, "yyyy-MM-dd HH:mm");
}
}
Cette approche est idéale pour les applications MVC complexes car elle centrailse la logique de sérialisation et garantit des formats de date cohérents et conformes aux standards (comme ISO 8601) à travers toute l'API.