Quelle est la meilleure alternative pour la sérialisation Java?

Je travaille actuellement sur un projet qui doit conserver tout type d’object (dont l’implémentation n’a pas de contrôle) afin que ces objects puissent être récupérés par la suite.

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 solution consistait à la sérialiser avec la sérialisation Java par défaut, mais nous avons eu beaucoup de mal à récupérer les objects lorsque les utilisateurs ont commencé à transmettre différentes versions du même object (atsortingbuts de types modifiés, noms, …).

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

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

Une bonne alternative?

La chose la plus simple à faire est d’utiliser la sérialisation, IMO, mais réfléchissez davantage à la forme sérialisée des classes (que vous devriez vraiment faire). Par exemple:

  1. Définir 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 faire l’object d’une reflection approfondie.

Je ne vais pas entrer dans beaucoup de détails, car à peu près tout ce que j’ai dit vient d’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 des solutions appropriées au problème:

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


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

XML marshalling

Comme beaucoup l’ont souligné, c’est une option, mais je pense que vous rencontrerez toujours les mêmes problèmes de compatibilité descendante. Cependant, avec le marshalling XML, vous obtiendrez sans doute ces résultats, car certains frameworks peuvent effectuer des vérifications pendant l’initialisation.

Conversion à / de YAML

C’est une idée avec laquelle j’ai joué, mais j’ai vraiment aimé le format YAML (au moins sous la forme d’un format toSsortingng () personnalisé). Mais en réalité, la seule différence pour vous est que vous vous dirigez vers YAML au lieu de XML. Le seul avantage est que YAML est légèrement plus lisible que XML. Les mêmes ressortingctions s’appliquent.

Nous sums en 2011 et dans un projet de services Web REST de qualité commerciale, nous utilisons les sérialiseurs suivants pour offrir aux clients différents types de supports:

  • XStream (pour XML mais pas pour JSON)
  • Jackson (pour JSON)
  • Kryo (un format de sérialisation binary rapide et compact)
  • Smile (un format binary fourni avec Jackson 1.6 et versions ultérieures).
  • Sérialisation d’objects Java.

Nous avons expérimenté avec d’autres sérialiseurs récemment:

  • SimpleXML semble solide, fonctionne deux fois plus vite que XStream, mais nécessite un peu trop de configuration pour notre situation.
  • YamlBeans avait quelques bogues.
  • SnakeYAML avait un bug mineur concernant les dates.

Jackson JSON, Kryo et Jackson Smile étaient tous nettement plus rapides que les bons anciens systèmes de sérialisation d’objects Java, d’environ 3x à 4,5x. XStream est sur le côté lent. Mais ce sont tous des choix solides à ce stade. Nous continuerons à surveiller les trois autres.

http://x-stream.github.io/ est sympa, regardez-le s’il vous plaît! Très pratique

de quelle implémentation nous n’avons aucun contrôle

La solution est de ne pas le faire . Si vous ne contrôlez pas 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 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 modifiés correctement 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. Ce serait trop coûteux pour vous de créer un système capable de faire face dynamicment à ce genre de corrections – il faut vraiment que ce soit le développeur de la classe qui conçoit la sérialisation.

En bref, votre conception est fausse – pas la technologie.

Google a mis au point un protocole binary – http://code.google.com/apis/protocolbuffers/ est plus rapide, a une charge utile inférieure à XML – que d’autres ont suggérée comme alternative.

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

Essayez de sérialiser sur json avec Gson par exemple.

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

Si la vitesse de sérialisation est importante pour vous, il existe un benchmark complet des sérialiseurs JVM ici:

Personnellement, j’utilise beaucoup Fame , car il offre une interopérabilité avec Smalltalk (VW et Squeak) et Python. (Déni de responsabilité, je suis le principal consortingbuteur du projet Fame.)

Peut-être Castor ?

Betwixt est une bonne bibliothèque pour la sérialisation des objects – mais ça ne va pas être une sorte de chose automatique. Si le nombre d’objects à sérialiser est relativement fixe, cela peut être une bonne option pour vous, mais si votre “client” vous lance de nouvelles classes tout le temps, cela peut représenter un effort supplémentaire ( 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 objects qu’ils vous envoient (ce qui les décharge de manière efficace).

Long et short – la sérialisation est difficile – il n’ya pas d’approche complètement mortelle. La sérialisation Java est aussi proche d’une solution de brain dead que je l’ai déjà vue, mais comme vous l’avez constaté, une utilisation incorrecte de la valeur de l’ID de version peut la casser. La sérialisation Java nécessite également l’utilisation de l’interface «Serializable» du marqueur, donc si vous ne pouvez pas contrôler votre source, vous avez un peu de mal à cela.

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

Une autre idée: utiliser le cache. Les caches permettent un contrôle, une évolutivité et une robustesse bien meilleurs de l’application. Encore faut-il sérialiser, mais la gestion devient beaucoup plus facile avec une structure de service de mise en cache. Le cache peut être conservé dans la mémoire, le disque, la firebase database ou la baie, ou toutes les options, l’un étant en débordement, en attente, avec basculement pour l’autre. Commons JCS et Ehcache sont deux implémentations Java, cette dernière est une solution d’entreprise gratuite jusqu’à 32 Go de stockage (avertissement: je ne travaille pas pour ehcache ;-)).