Vous devez savoir que toutes les classes ne sont pas conçues pour être (dé) sérialisées, en particulier si la (dé) sérialisation est basée sur la structure binaire de la classe cible. Votre approche a au moins les points faibles suivants:
- les
sun.awt.image.ByteInterleavedRaster
champs de classe ne sont pas nécessairement les mêmes sur une autre machine virtuelle Java/JRE, vous pouvez ainsi obtenir être verrouillé fournisseur;
- données binaires persistantes dans JSON n'est probablement pas le meilleur choix (probablement énorme et terrible consommation de mémoire lors de (dé) sérialisation, consommation de stockage, performance) - peut-être un stockage blob générique est mieux pour les données binaires? Lire une image avec Java AWT et la réécrire ne garantit pas la même sortie binaire: par exemple, mon image de test, 1,2K, a été désérialisée en tant qu'image d'une autre taille, 0,9 K;
- Vous devez choisir le format d'image persistant cible ou détecter le format le plus efficace (comment?).
Considérez la classe simple suivante:
final class ImageHolder {
final RenderedImage image;
ImageHolder(final RenderedImage image) {
this.image = image;
}
}
Maintenant, vous devez créer un adaptateur de type à dire Gson comment une instance de type particulier peut être stocké et restauré:
final class RenderedImageTypeAdapter
extends TypeAdapter<RenderedImage> {
private static final TypeAdapter<RenderedImage> renderedImageTypeAdapter = new RenderedImageTypeAdapter().nullSafe();
private RenderedImageTypeAdapter() {
}
static TypeAdapter<RenderedImage> getRenderedImageTypeAdapter() {
return renderedImageTypeAdapter;
}
@Override
@SuppressWarnings("resource")
public void write(final JsonWriter out, final RenderedImage image)
throws IOException {
// Intermediate buffer
final ByteArrayOutputStream output = new ByteArrayOutputStream();
// By the way, how to pick up the target image format? BMP takes more space, PNG takes more time, JPEG is lossy...
ImageIO.write(image, "PNG", output);
// Not sure about this, but converting to base64 is more JSON-friendly
final Base64.Encoder encoder = Base64.getEncoder();
// toByteArray() returns a copy, not the original array (x2 more memory)
// + creating a string requires more memory to create the String internal buffer (x3 more memory)
final String imageBase64 = encoder.encodeToString(output.toByteArray());
out.value(imageBase64);
}
@Override
public RenderedImage read(final JsonReader in)
throws IOException {
// The same in reverse order
final String imageBase64 = in.nextString();
final Base64.Decoder decoder = Base64.getDecoder();
final byte[] input = decoder.decode(imageBase64);
return ImageIO.read(new ByteArrayInputStream(input));
}
}
Notez que Gson n'est actuellement pas très bien conçu pour prendre en charge la transformation des octets, mais il pourrait être à l'avenir somewhat better s'il est corrigé.
Exemple d'utilisation:
private static final Gson gson = new GsonBuilder()
.registerTypeHierarchyAdapter(RenderedImage.class, getRenderedImageTypeAdapter())
.create();
public static void main(final String... args)
throws IOException {
try (final InputStream inputStream = getPackageResourceInputStream(Q43301580.class, "sample.png")) {
final RenderedImage image = ImageIO.read(inputStream);
final ImageHolder before = new ImageHolder(image);
final String json = gson.toJson(before);
System.out.println(json);
final ImageHolder after = gson.fromJson(json, ImageHolder.class);
...
}
}
Exemple de sortie (avec du vrai petit (32x32) fichier PNG intérieur):
{ "image": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADgklEQVR42t2XXUiTYRTHpxj4kSKShhgYGSihZGIXXYhU5J2BhBIhCH5cCF6oiWhG0k1BpHghgRgoJHiloBKEqFQ3frDNuemaOqdu0 + n8mFM3Nzf37z1n + JZUEPlOoQdetvd5L87vOed/Ph4ZznnJzsqQz + UFZ + M5HwBrezuUFy9CERoKY3U1jtzuwAFY29pgGxgQ350aDVSXLmFfLud9eVAQTHV1gQNYKi + HMiwM9uFhft/o6MBcTg6fWp + XB93duzhyOOA7POSwyAIR64UnTxhi9 + tXfhQhIdBlZ2P2wQM2Tmv11StY3rwJjAYIQl9QAGVUFPZGRzF7/z7kwcGw9ffzt80PHzAZE4ODu TnpAQ50OjgmJ3HkcmE + N5chdr98wfzDh5DLZPyo4uOx +/mz9Bqg + B8b0d6 + zSecFeJPInSo1XAbjXAKvxR/yUW4Pz7uV/vEBJ9OffUqNNev49BiYeGp4uLg0usDUwdIUNNpaTDV1op7rqUljvNKYyMLb7G4GIdWa2AAbH19LDIy8vNaefmSBRiQUkynMtXUYLGkBO7lZWx2dTEEnVjURFnZL1CSASyWlmL6xg1okpIwdeUK3CYTNjo7WYCGoiLOeU1yMtxmc2AA1NeuscA829uYTk1lEIJYf/eOIcgzP6tdEgAyRicjtatiY8V9EhdDpKTw/7XmZoYgGEkBzEITIQDzs2dsYPX1a/EbuZq8YG5o8GeG8E2dmIgjp/P0AJxGgku1GRnYVyh479jVdFrRE + vrXGqPl3dvTxoPeO12aDMz2aBDqRT315qa/VTR/wTgsdmw1d3NJVSMs + BmOqlYhARXL1dUSA/gWljg9FKGh/u72tgYQ1BqEcjvqtqpAHY + fcLOx4/+ durzcTOxvH3LXY1qOUFQ/CnVyAszN2 + eGK1OBWCur4cyIgIrL174Xb + 1hdl79xiERioqOFRSKf3sQ0MclvXWVmk8sN3b6 + 9UBsMvQwWtb3fuwD4ywpkwlZDAojNWVUk3lhsrK7Hw + PHJ + AudzKnVwrOzwwYP5ud50JhJT5cs9iLAxvv3UFy4wLVdn58P1eXLP4YKIfWor09GR0MZGYm1lhbpLyYUZ/Pz55i5dQu6rCwYnz4FhYXmNjJKKbYmiHG7p + fsb0aGwkIsC2PWuVzNaJ5j1Q8Oni0AVTkKCbmffs/8cuoVlK9/9IjHrP/qdvyn9R0SEM4flWsmCwAAAABJRU5ErkJggg \ u003d \ u003d "}
Je pense qu'il ya trop de défauts, et je vous recommande fortement de re-concevoir votre stockage binaires si possible et de stocker le contenu binaire tel quel.
Voulez-vous dire que vous le conservez comme un binaire du côté client? Je ne fais aucune conversation du côté du serveur? – kiwicomb123
@ kiwicomb123 Cela dépend de ce dont vous avez vraiment besoin dans votre cas. L'utilisation d'une image tamponnée résultera en une conversion d'image (est-ce acceptable?). En outre, le passer par JSON _using_ Gson n'est peut-être pas le meilleur choix, car Gson exige que toute la chaîne soit lue/écrite depuis/vers le flux JSON, pas par morceaux (peut-être que d'autres bibliothèques JSON peuvent le faire mieux?). En gardant simplement le binaire et en le stockant tel quel (vous pouvez appliquer une validation avant le téléchargement, bien sûr), vous pouvez simplement exposer le binaire via une URL directe (bien sûr, certaines autorisations peuvent aussi être appliquées). –
@ kiwicomb123 Vous pouvez également expérimenter avec https://fasterxml.github.io/jackson-core/javadoc/2.6/com/fasterxml/jackson/core/JsonGenerator.html et http://fasterxml.github.io/jackson -core/javadoc/2.6/com/fasterxml/jackson/core/JsonParser.html - ils semblent prendre en charge les données brutes afin que vous puissiez essayer de combiner différents flux d'entrée/sortie afin de produire/valider vos données et les écrire directement sur JSON. –