Question

Je travaille actuellement sur un projet qui doit conserver tout type d’objet (dont nous n’avons aucun contrôle sur la mise en oeuvre) afin que ces objets puissent être récupérés ultérieurement.

Nous ne pouvons pas implémenter un ORM car nous ne pouvons pas restreindre les utilisateurs de notre bibliothèque au moment du développement.

Notre première alternative consistait à le sérialiser avec la sérialisation Java par défaut, mais nous avions beaucoup de difficulté à récupérer les objets lorsque les utilisateurs commençaient à transmettre différentes versions du même objet (attributs modifiés types, noms, ...).

Nous avons essayé avec la classe XMLEncoder (transforme un objet en XML), mais nous avons constaté un manque de fonctionnalités (ne prend pas en charge Enums, par exemple).

Enfin, nous avons également essayé JAXB, mais cela impose à nos utilisateurs d’annoter leurs classes.

Une bonne alternative?

Était-ce utile?

La solution

La chose la plus facile à faire pour vous est toujours d’utiliser la sérialisation, IMO, mais de réfléchir davantage à la forme sérialisée des classes (ce que vous devriez vraiment faire de toute façon). Par exemple:

  1. Définissez explicitement le SerialUID.
  2. Définissez votre propre formulaire sérialisé, le cas échéant.

Le formulaire sérialisé fait partie de l'API de la classe et sa conception doit être soigneusement pensée.

Je n’entrerai pas dans les détails, car à peu près tout ce que j’ai dit provient de Effective Java. Je vais plutôt vous y référer, en particulier les chapitres sur la sérialisation. Il vous avertit de tous les problèmes que vous rencontrez et fournit les solutions appropriées:

http://www.amazon.com/Effective-Java-2nd-Joshua- Bloch / dp / 0321356683

Cela dit, si vous envisagez toujours une approche de non-sérialisation, en voici quelques-uns:

Classement XML

Comme beaucoup l'ont fait remarquer, il existe une option, mais je pense que vous rencontrez toujours les mêmes problèmes de compatibilité ascendante. Cependant, avec le marshalling XML, nous espérons pouvoir les détecter immédiatement, car certains frameworks peuvent effectuer certaines vérifications à votre place lors de l'initialisation.

Conversion vers / depuis YAML

C’est une idée à laquelle je m’intéressais, mais j’ai vraiment aimé le format YAML (au moins en tant que format personnalisé toString ()). Mais, en réalité, la seule différence est que vous vous dirigeriez vers YAML au lieu de XML. Le seul avantage est que YAML est légèrement plus lisible que XML. Les mêmes restrictions s'appliquent.

Autres conseils

Nous sommes en 2011 et, dans le cadre d'un projet de services Web REST de niveau commercial, nous utilisons les sérialiseurs suivants pour offrir aux clients une variété de types de supports:

  • XStream (pour XML mais pas pour JSON)
  • Jackson (pour JSON)
  • Kryo (format de sérialisation binaire rapide et compact)
  • Smile (format binaire fourni avec Jackson 1.6 et versions ultérieures).
  • Sérialisation des objets Java.

Nous avons récemment testé d'autres sérialiseurs:

  • SimpleXML semble solide, fonctionne à la vitesse 2x de XStream, mais nécessite un peu trop de configuration pour notre situation.
  • YamlBeans présentait quelques problèmes.
  • SnakeYAML présentait un bogue mineur lié aux dates.

Jackson JSON, Kryo et Jackson Smile étaient tous nettement plus rapides que la bonne vieille sérialisation des objets Java, d’environ 3x à 4,5x. XStream est un peu lent. Mais ce sont tous des choix solides à ce stade. Nous continuerons à surveiller les trois autres.

http://x-stream.github.io/ est agréable, merci de prendre une Regarde ça! Très pratique

  

dont nous n'avons aucun contrôle sur la mise en oeuvre

La solution est ne faites pas cela . Si vous n'avez pas le contrôle de l'implémentation d'un type, vous ne devriez pas le sérialiser. Fin de l'histoire. La sérialisation Java fournit serialVersionUID spécifiquement pour gérer les incompatibilités de sérialisation entre les différentes versions d'un type. Si vous ne contrôlez pas l'implémentation, vous ne pouvez pas être sûr que les ID sont correctement modifiés lorsqu'un développeur modifie une classe.

Prenons un exemple simple de "Point". Il peut être représenté par un système de coordonnées cartésien ou polaire. Construire un système capable de gérer dynamiquement ce type de corrections vous coûterait très cher, c’est bien le développeur de la classe qui conçoit la sérialisation.

En bref, c'est votre conception qui ne va pas - pas la technologie.

Google a créé un protocole binaire - http://code.google.com/apis/ protocolbuffers / est plus rapide, sa charge utile est plus petite que celle de XML - ce que d’autres ont suggéré comme alternative.

L’un des avantages des tampons de protocole est qu’il peut échanger des informations en C, C ++, Python et Java.

Essayez de sérialiser json avec Gson par exemple.

Egalement un remplacement très rapide de la sérialisation JDK: http://ruedigermoeller.github.io/fast-serialization/

Si la rapidité de la sérialisation est importante pour vous, vous trouverez ici un exemple complet des sérialiseurs JVM:

Personnellement, j'utilise beaucoup de Fame , car il offre une interopérabilité avec Smalltalk (VW et Squeak) et Python. (Avertissement, je suis le principal contributeur du projet Fame.)

Peut-être Castor ?

Betwixt est une bonne bibliothèque pour la sérialisation d'objets - mais cela ne sera pas automatique. de chose. Si le nombre d'objets que vous devez sérialiser est relativement fixe, cela peut être une bonne option pour vous, mais si votre «client» doit vous lancer de nouvelles classes tout le temps, il se peut que cela demande plus d'effort qu'il n'en vaut la peine ( Certainement plus facile que XMLEncoder pour tous les cas particuliers, cependant).

Une autre approche consiste à demander à votre client de fournir les fichiers .betwixt appropriés pour tous les objets qu’il vous jette (ce qui lui décharge la responsabilité).

Long et court - la sérialisation est difficile - il n’existe pas d’approche complètement mortelle. La sérialisation Java est aussi proche d'une solution mortelle que je ne l'ai jamais vue, mais comme vous l'avez constaté, une utilisation incorrecte de la valeur de la version uid peut la perturber. La sérialisation Java nécessite également l’utilisation de l’interface de marqueur 'Serializable', donc si vous ne pouvez pas contrôler votre source, vous n’avez pas de chance avec celle-là.

Si l'exigence est vraiment aussi ardue que vous le décrivez, vous devrez peut-être recourir à une sorte de BCE (modification du code octet) sur les objets / aspects / peu importe. Cela sort du cadre d’un petit projet de développement et du domaine d’Hibernate, de Casper ou d’un ORM ....

Autre idée: utiliser le cache. Les caches offrent un contrôle, une évolutivité et une robustesse bien meilleurs pour l'application. Reste à sérialiser, cependant, mais la gestion devient beaucoup plus facile avec un framework de service de mise en cache. Le cache peut être conservé dans la mémoire, le disque, la base de données ou la matrice - ou toutes les options -, l'une étant un dépassement de capacité, une mise en veille, un basculement pour l'autre. Commons JCS et Ehcache sont deux implémentations Java, ce dernier est une solution d'entreprise offrant jusqu'à 32 Go de stockage (avertissement: je ne travaille pas pour ehcache ;-)).

SBE est une bibliothèque établie pour la bibliothèque de sérialisation rapide basée sur des octets, et capable de gérer les versions. Cependant, il est un peu difficile à utiliser car vous devez écrire des classes wrapper de longueur dessus.

À la lumière de ses faiblesses, j’ai récemment créé une bibliothèque de sérialisation Java uniquement, inspirée du protocole SBE et du protocole FIX (protocole commun du marché financier permettant d’échanger des messages de transaction / citation), qui tente de conserver les avantages des deux tout en surmontant leurs problèmes. faiblesses. Vous pouvez consulter https://github.com/iceberglet/anymsg

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top