IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Format d'échange (XML, JSON...) Java Discussion :

Sérialisation/Désérialisation de Dates [XStream]


Sujet :

Format d'échange (XML, JSON...) Java

  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 8
    Points : 5
    Points
    5
    Par défaut Sérialisation/Désérialisation de Dates
    Bonjour à tous,

    J'ai un problème très curieux lorsque je sérialise/désérialise des objets de type Date avec XStream.

    Ce problème se produit aléatoirement sur certaines dates. Après sérialisation/désérialisation, la date est différente de celle d'origine (!?!). Il y a un décalage de 3039 secs entre les 2 dates (systématique !)

    Je l'ai constaté avec les dates suivantes :
    -> 1900-06-02 00:00:00
    -> 1910-06-02 00:00:00

    Je pensais au départ que les dates étaient trop anciennes mais ce n'est pas le cas, puisque la date "1700-06-02 00:00:00" fonctionne correctement.

    J'utilise Java 1.4.2 et XStream 1.2.2.

    Voici mon code de test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
     
    package test;
     
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.io.xml.DomDriver;
     
    public class Main2 {
     
     
    	public static Object chargerXML(String cheminFichier) throws IOException {
     
    		Object o = null;
    		XStream xstream = new XStream( new DomDriver( "ISO-8859-1" ) );
    		File file = new File(cheminFichier);
    		FileInputStream fis;
    		fis = new FileInputStream( file );
    		try {
    			o =  xstream.fromXML(fis);
    		}
    		finally{
    			fis.close();
    		}
    		return o;
    	}
     
    	public static void serialiserXML(String cheminFichier, Object objetMetier) throws IOException {
     
    		XStream xstream = new XStream(new DomDriver( "ISO-8859-1" ));
    		File fichier = new File(cheminFichier);
    		if( ! fichier.exists() ) fichier.createNewFile();
    		FileOutputStream fos = new FileOutputStream(fichier);
    		try{
    			fos.write( "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>".getBytes() );
    			xstream.toXML(objetMetier, fos);
    		}
    		finally{
    			fos.close();
    		}
     
    	}
     
    	public static void main(String[] args) {
    		try{
    			Date date1;
    			Date date2;
     
    			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     
     
    			date1 = dateFormat.parse( "1700-06-02 00:00:00" );
    			serialiserXML( "date1.xml" , date1 );
    			date2 = (Date) chargerXML( "date1.xml" );
    			System.out.println("Avant sérialisation/chargement : " + dateFormat.format( date1 ));
    			System.out.println("Après sérialisation/chargement : " + dateFormat.format( date2 )  );
    			System.out.println();
     
     
    			date1 = dateFormat.parse( "1900-06-02 00:00:00" );
    			serialiserXML( "date2.xml" , date1 );
    			date2 = (Date) chargerXML( "date2.xml" );
    			System.out.println("Avant sérialisation/chargement : " + dateFormat.format( date1 ));
    			System.out.println("Après sérialisation/chargement : " + dateFormat.format( date2 )  );
    			System.out.println();
     
     
    			date1 = dateFormat.parse( "1910-06-02 00:00:00" );
    			serialiserXML( "date3.xml" , date1 );
    			date2 = (Date) chargerXML( "date3.xml" );
    			System.out.println("Avant sérialisation/chargement : " + dateFormat.format( date1 ));
    			System.out.println("Après sérialisation/chargement : " + dateFormat.format( date2 )  );
    			System.out.println();
     
     
    			date1 = dateFormat.parse( "1950-06-14 09:00:00" );
    			serialiserXML( "date4.xml" , date1 );
    			date2 = (Date) chargerXML( "date4.xml" );
    			System.out.println("Avant sérialisation/chargement : " + dateFormat.format( date1 ));
    			System.out.println("Après sérialisation/chargement : " + dateFormat.format( date2 )  );
    			System.out.println();
     
     
    		}
    		catch( Throwable t ){
    			t.printStackTrace();
    		}
    	}
    }
    Ce code affiche sur la sortie standard :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Avant sérialisation/chargement : 1700-06-02 00:00:00
    Après sérialisation/chargement : 1700-06-02 00:00:00
     
    Avant sérialisation/chargement : 1900-06-02 00:00:00
    Après sérialisation/chargement : 1900-06-01 23:09:21
     
    Avant sérialisation/chargement : 1910-06-02 00:00:00
    Après sérialisation/chargement : 1910-06-01 23:09:21
     
    Avant sérialisation/chargement : 1950-06-14 09:00:00
    Après sérialisation/chargement : 1950-06-14 09:00:00
    A noter que les fichiers XML résultant de la date d'origine contiennent la bonne date. Par exemple, voici le contenu de date2.xml :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <?xml version="1.0" encoding="ISO-8859-1"?><date>1910-06-02 00:00:00.0 CET</date>
    Ce problème intervient donc lors de la désérialisation.

    Je ne comprends vraiment pas à quoi c'est dû...
    D'où mes questions :
    -> Est-ce que quelqu'un a déjà eu ce problème ?
    -> Peut-on y faire quelque chose ou s'agit-t-il d'un bug de XStream ?

    Merci d'avance pour vos réponses...

  2. #2
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Après m'être plongé dans le code d'XStream, j'ai pu reproduire l'erreur...

    Les simples lignes suivantes permettent de la reproduire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z");
    String str = "1900-02-23 00:00:00.0 CET";
    System.out.println( dateFormat2.parseObject( str ) );
    Ce qui donne sur la sortie standard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1900-02-22 23:09:21.0 CET
    Cela ne semble donc pas être lié à XStream...
    Bizarre bizarre

  3. #3
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    J'ai réglé le problème en créant un nouveau convertisseur XStream pour le type java.util.date :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package test;
     
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
     
    import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
     
    public class SimpleDateConverter extends AbstractSingleValueConverter{
     
    	private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
     
    	public boolean canConvert(Class type) {
    		return type.equals( Date.class );
    	}
     
    	public Object fromString(String str) {
    		Date date;
    		try {
    			date = dateFormat.parse( str );
    		} catch (ParseException e) {
    			date = null;
    		}
    		return date;
    	}
     
    	public String toString(Object obj) {
    		Date date = (Date) obj;
    		return dateFormat.format( date );
    	}
     
     
    }
    Il faut ensuite référencer ce nouveau convertisseur dans XStream. Les fonctions de sérialisation/déserialisation deviennent les suivantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    	public static Object chargerXML(String cheminFichier) throws IOException {
     
    		Object o = null;
    		XStream xstream = new XStream( new DomDriver( "ISO-8859-1" ) );
     
    		xstream.registerConverter(new SimpleDateConverter());
     
    		File file = new File(cheminFichier);
    		FileInputStream fis;
    		fis = new FileInputStream( file );
    		try {
    			o =  xstream.fromXML(fis);
    		}
    		finally{
    			fis.close();
    		}
    		return o;
    	}
     
    	public static void serialiserXML(String cheminFichier, Object objetMetier) throws IOException {
     
    		XStream xstream = new XStream(new DomDriver( "ISO-8859-1" ));
     
    		xstream.registerConverter(new SimpleDateConverter());
     
    		File fichier = new File(cheminFichier);
    		if( ! fichier.exists() ) fichier.createNewFile();
    		FileOutputStream fos = new FileOutputStream(fichier);
    		try{
    			fos.write( "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>".getBytes() );
    			xstream.toXML(objetMetier, fos);
    		}
    		finally{
    			fos.close();
    		}
     
    	}
    Le problème est donc résolu mais j'avoue ne pas trop comprendre ce comportement du DateParser...

    A+

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    Si tu enleve le z dans le format le résultat est correct!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    String str = "1900-02-23 00:00:00.0";
    System.out.println( dateFormat2.parseObject( str ) );

  5. #5
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    8
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 8
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par hibour Voir le message
    Si tu enleve le z dans le format le résultat est correct!
    Oui c'est ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z");
    String str = "1900-02-23 00:00:00.0 CET";
    System.out.println( dateFormat2.format( dateFormat2.parseObject( str ) ) );
    ne fonctionne pas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    String str = "1900-02-23 00:00:00.0";
    System.out.println( dateFormat2.format( dateFormat2.parseObject( str ) ) );
    fonctionne

    Il doit y avoir une bonne raison à ça mais je ne vois pas laquelle...

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    En attendant d'avoir une bonne explication tu peux rajouter le time zone manuellement après..

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Problème Sérialisation/Désérialisation
    Par sorry60 dans le forum Silverlight
    Réponses: 29
    Dernier message: 25/06/2010, 11h34
  2. Problème de sérialisation / désérialisation
    Par angedejupiter dans le forum C#
    Réponses: 1
    Dernier message: 07/09/2009, 10h18
  3. sérialiser/désérialiser une Hashtable : pb de cast(?)
    Par zouzoute dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 02/02/2008, 15h22
  4. sérialisation désérialisation
    Par hug dans le forum Langage
    Réponses: 2
    Dernier message: 16/01/2006, 14h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo