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

Langage Java Discussion :

Sérialiser un objet et récupérer un String (pour le stocker en base de données)


Sujet :

Langage Java

  1. #1
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut Sérialiser un objet et récupérer un String (pour le stocker en base de données)
    Bonjour,

    Je découvre la sérialisation en Java.
    En PHP il m'était très simple de sérialiser un objet et désérialiser sous forme de chaine de caractères, je remarque qu'en Java ce n'est pas aussi simple.

    J'ai donc effectué des recherches et le meilleur exemple que j'ai trouvé est :
    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
    import java.util.*;
    import java.io.*;
     
    /** 
     * Usage sample serializing SomeClass instance 
     */
    public class ToStringSample {
        public static void main( String [] args )  throws IOException,
                                                          ClassNotFoundException {
            String string = toString( new SomeClass() );
            System.out.println(" Encoded serialized version " );
            System.out.println( string );
            SomeClass some = ( SomeClass ) fromString( string );
            System.out.println( "\n\nReconstituted object");
            System.out.println( some );
     
     
        }
     
        /** Read the object from Base64 string. */
        private static Object fromString( String s ) throws IOException ,
                                                            ClassNotFoundException {
            byte [] data = Base64Coder.decode( s );
            ObjectInputStream ois = new ObjectInputStream( 
                                            new ByteArrayInputStream(  data ) );
            Object o  = ois.readObject();
            ois.close();
            return o;
        }
     
        /** Write the object to a Base64 string. */
        private static String toString( Serializable o ) throws IOException {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream( baos );
            oos.writeObject( o );
            oos.close();
            return new String( Base64Coder.encode( baos.toByteArray() ) );
        }
    }
     
    /** Test subject. A very simple class. */ 
    class SomeClass implements Serializable{
        int i = Integer.MAX_VALUE;
        String s = "ABCDEFGHIJKLMNOP";
        Double d = new Double( -1.0 );
        public String toString(){
            return  "SomeClass instance says: Don't worry, " +
                    "I'm healty. Look, my data is i = " + i  + ", s = " + s + ", d = " + d;
        }
    }
    Source ici.

    L'auteur précise bien que Java n'implémente pas ce genre de fonctionnalité à la base :
    Java does not have a "public" implementation for that (though sun.misc, and java.util.prefs have implementations and the source is available, but check the license for those).
    Sun (ou Oracle) n'a t-il vraiment pas prévu ce genre de cas pour envoyer un objet sous forme de chaine de caractère vers une base de données ou vers une ligne de commande ?

    En tant normal, comment fait-t-on pour envoyer un objet sur le réseaux (socket), se sert-t-on uniquement d'un objet ObjectInputStream ?


    Merci
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    par réseau (socket) -> on envoie du binaire directement, ça me semble logique

    Quand tu as besoin de protéger des données brutes (que ce soit des objets sérialisés ou tout autre chose), les pratiques les plus courantes veulent qu'on utilise un codage en base64, comme tu le fais.


    Et pour le stockage dans une base de données, il y a plusieurs pratiques possibles:

    1) tu sérialize mais alors tu utilise un champ blob (faut rester logique dans tes tables)
    2) tu met sous forme de varchar -> mais alors tu demande à ton objet de fournir des méthodes genre public String toExternalForm() ou public String fromExternal qui donnera des données compréhensibles du genre une structure json. Tu peux aussi trouver des librairies qui sérializent en json directement
    3) sur les SGBD qui le supportent, tu utilise jaxb (standard) ou xstream (librairies à part) poru sérialiser en XML et tu crée un champ xml dans ta table.

    L'avantage des deux derniers cas (surtout du dernier), c'est que les données de ton objet deviennent requêtable en SQL

  3. #3
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    J'ai découvert la sérialisation avec PHP, celui-ci effectue une transformation des objets en chaine de caractères.

    La sérialisation Java est en binaire. D'ailleurs je me demande, si on sérialise un objet Java (donc en binaire) sous Windows, pourra-t-on l'utiliser sous Linux ?
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par Gugelhupf Voir le message
    D'ailleurs je me demande, si on sérialise un objet Java (donc en binaire) sous Windows, pourra-t-on l'utiliser sous Linux ?
    Oui...

    Mais attention à la sérialisation qui est très sensible à la variation des objets (il faut penser à définir le serialUID par exemple).



    Mais dans ton cas si c'est pour sauver dans une BD sous format texte, je ne pense pas que la sérialisation Java soit une bonne solution.



    Perso j'opterais pour une sérialisation en texte :
    • Soit en utilisant l'API standard et les XMLEncoder/XMLDecoder qui transformeront ton objet en XML, par exemple :
      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
          private static Object fromString(String s) throws IOException ,
                                                              ClassNotFoundException {
          	XMLDecoder decoder = new XMLDecoder(new ByteArrayInputStream(s.getBytes("UTF-8")));
          	try {
          		return decoder.readObject();
          	} finally {
          		decoder.close();
          	}
          }
       
          private static String toString(Object o) throws UnsupportedEncodingException {
          	ByteArrayOutputStream out = new ByteArrayOutputStream();
              XMLEncoder encoder = new XMLEncoder(out);
              try {
              	encoder.writeObject(o);
              } finally {
              	encoder.close();
              }
              return new String(out.toByteArray(), "UTF-8");
          }

    • Soit en utilisant une librairie pour exporter en JSON, ce qui me semble bien plus adapté.
      Par exemple perso dans un cas similaire j'utilise Gson :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
              SomeClass object = ...
       
              Gson gson = new Gson();
       
              // "sérialisation" :
              String json = gson.toJson(object);
       
              // "désérialisation"
              SomeClass someObject = gson.fromJson(json, SomeClass.class);




    a++

  5. #5
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    La sérialisation Java est en binaire. D'ailleurs je me demande, si on sérialise un objet Java (donc en binaire) sous Windows, pourra-t-on l'utiliser sous Linux ?
    Ca dépends. normalement, ce n'est pas influencé par l'OS.

    Par contre, pour toute une série de classes de la JVM, ça dépends de la version de la JVM. En général c'est indiqué dans la javadoc. Exemple, JPanel
    Warning: Serialized objects of this class will not be compatible with future Swing releases. The current serialization support is appropriate for short term storage or RMI between applications running the same version of Swing. As of 1.4, support for long term storage of all JavaBeansTM has been added to the java.beans package. Please see XMLEncoder.

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Avec la serialization de Java il faut faire très attention car on risque d'apporter des incompatibilités.

    Déjà il faut définir un serialVersionUID.
    En effet si ce numéro change cela provoquera une erreur. Or par défaut ce numéro est généré automatiquement et la moindre modif dans le code de la classe peut provoquer une incompatibilité : le simple fait d'ajouter une méthode peut alors tout casser !

    Ensuite il faut gérer manuellement l'évolution de la classe (ajout/suppression d'attribut). Il y a plusieurs moyens pour cela, mais cela peut vite devenir assez complexe...

    Avec XMLEncoder ou JSON on n'a pas ces soucis : les valeurs/attributs absents sont simplement ignorés...


    a++

  7. #7
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Je pensais que la sérialisation vers du binaire en Java pouvait créer des problèmes entre 2 OS (ex: Linux/Windows) ou 2 processeurs différents (Little Endian & Big Endian).

    Autrement comment les gens auraient-t-ils fait pour envoyer des objets via les sockets ?

    Donc la prochaine fois que je penserais sérialisation :
    • XML (même si ça donne des fichiers un peu lourd)
    • JSON (solution pas standard pour le moment)



    Je vous remercie pour vos réponses
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    • XML (même si ça donne des fichiers un peu lourd)
    • JSON (solution pas standard pour le moment)
    Le xml peux être zippé, c'est comme ça qu'est géré le format opendocument

    Tu peux garder la sérialisation pour TES classes, à condition de bien la gérer. Pour ça le plus "simple" est d'implémenter Externalizable plutot que Serializable, ça te donne le controle sur le processus et te permet de gérer les mises à jour. Mais comme on t'as dit, ça deviens vite complexe à gérer. Des outils comme jaxb sont plus souple là dessus. Autant s'en servir

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 11/09/2013, 10h44
  2. Réponses: 0
    Dernier message: 20/04/2012, 01h06
  3. Réponses: 1
    Dernier message: 25/11/2008, 11h11
  4. procédure pour exporter et importer bases de données
    Par mariogarcia dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 24/03/2006, 17h33
  5. Réponses: 4
    Dernier message: 18/01/2006, 21h30

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