2010-06-23 8 views
0

J'essaie de lire un objet JSON qui contient la date et l'heure dans un format qui ne peut pas être analysé directement par la structure DateTime de .NET. Pour éviter d'avoir un champ « int » dans ma structure pour la date/heure, je l'ai écrit un DateTimeConverter personnalisé:Pourquoi JavaScriptSerializer ignore-t-il mon convertisseur?

public class DateTimeConverter : JavaScriptConverter { 
    public override IEnumerable<Type> SupportedTypes { 
    get { return new Type[] { typeof(DateTime), typeof(DateTime?) }; } 
    } 

    public override IDictionary<string, object> Serialize(
    object obj, JavaScriptSerializer serializer 
) { throw new NotImplementedException(); } 

    public override object Deserialize(
    IDictionary<string, object> dictionary, Type type, 
    JavaScriptSerializer serializer 
) { 
    return DateTime.Now; 
    } 
} 

Mais quand je lis une chaîne JSON avec le JavaScriptSerializer, il n'utilise pas mon convertisseur personnalisé :

public struct TextAndDate { 
    public string Text; 
    public DateTime Date; 
} 

static void Main() { 
    string json = 
    "{" + 
    " \"text\": \"hello\", " + 
    " \"date\": \"1276692024\"" + 
    "}"; 

    var serializer = new JavaScriptSerializer(); 
    serializer.RegisterConverters(new [] { new DateTimeConverter() }); 
    var test = serializer.Deserialize<TextAndDate>(json); 
} 

Le convertisseur est utilisé quand je deserialize directement une valeur DateTime, mais pas quand je deserialize un type contenant une valeur DateTime.

Pourquoi? Un moyen de contourner cela sans écrire un type DateTime personnalisé ou en utilisant int?

+0

Je devine simplement: il a déjà trouvé une correspondance dans les gestionnaires intégrés ... donc ne cherche pas plus. –

+0

Non ce n'est pas ça. Si je désérialise un DateTime directement, mon convertisseur personnalisé est utilisé. Voir aussi MSDN: "Plusieurs convertisseurs peuvent être enregistrés avec la même instance JavaScriptSerializer, et ces convertisseurs peuvent indiquer un support pour le même type, ce qui fait que le dernier convertisseur enregistré pour un type spécifique est celui qui sera utilisé par JavaScriptSerializer pour sérialiser le type. " – Cygon

Répondre

0

Vous devriez faire de petits changements dans votre DateTimeConverter classe:

public class DateTimeConverter : JavaScriptConverter { 
    public override IEnumerable<Type> SupportedTypes { 
     get { return new Type[] { typeof (TextAndDate) }; } 
    } 

    public override IDictionary<string, object> Serialize (
     object obj, JavaScriptSerializer serializer 
    ) { throw new NotImplementedException(); } 

    public override object Deserialize (
     IDictionary<string, object> dictionary, Type type, 
     JavaScriptSerializer serializer 
    ) { 
     if (type == typeof (TextAndDate)) { 
      TextAndDate td = new TextAndDate(); 
      if (dictionary.ContainsKey ("text")) 
       td.Text = serializer.ConvertToType<string> (
              dictionary["text"]); 
      //if (dictionary.ContainsKey ("date")) 
       td.Date = DateTime.Now; 
      return td; 
     } 
     else 
      return null; 
    } 
} 

MISE À JOUR basé sur le commentaire: Il me semble que vous devez utiliser un message technique inspecteurs (voir http://msdn.microsoft.com/en-us/library/aa717047.aspx). Regardez How to ignore timezone of DateTime in .NET WCF client? pour un exemple.

+0

Merci, mais tout en enregistrant mon convertisseur pour le type 'TextAndDate' lui-même pourrait fonctionner, je devrais alors écrire un convertisseur personnalisé pour chaque type JSON racine retourné par l'API REST. Dans les convertisseurs, je devrais également associer tous les champs manuellement (comme vous le faites dans votre exemple) ou réimplémenter l'association de champ automatique normalement effectuée par JavaScriptSerializer. – Cygon