Wie deserialisiere ich eine Liste mit GSON oder einer anderen JSON-Bibliothek in Java?

121

Ich kann ein List<Video>in meinem Servlet auf GAE serialisieren , aber ich kann es nicht deserialisieren. Was mache ich falsch?

Dies ist mein Klassenvideo in GAE, das serialisiert ist:

package legiontube;

import java.util.Date;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Video {

    @PrimaryKey
    private String id;

    @Persistent
    private String titulo;

    @Persistent
    private String descricao;

    @Persistent
    private Date date;

    public Video(){};

 public Video(String id, String titulo, String descricao, Date date) {
  //super();
  this.id = id;
  this.titulo = titulo;
  this.descricao = descricao;
  this.date = date;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getTitulo() {
  return titulo;
 }

 public void setTitulo(String titulo) {
  this.titulo = titulo;
 }

 public String getDescricao() {
  return descricao;
 }

 public void setDescricao(String descricao) {
  this.descricao = descricao;
 }

 public Date getDate() {
  return date;
 }

 public void setDate(Date date) {
  this.date = date;
 }

}

Dies ist mein Klassenvideo in meiner anderen Anwendung, in der ich versuche zu deserialisieren:

package classes;

import java.util.Date;

public class Video {
 private String id;
 private String titulo;
 private String descricao;
 private Date date;

 public Video(String id, String titulo, String descricao, Date date) {
  //super();
  this.id = id;
  this.titulo = titulo;
  this.descricao = descricao;
  this.date = date;
 }

 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getTitulo() {
  return titulo;
 }
 public void setTitulo(String titulo) {
  this.titulo = titulo;
 }
 public String getDescricao() {
  return descricao;
 }
 public void setDescricao(String descricao) {
  this.descricao = descricao;
 }
 public Date getDate() {
  return date;
 }
 public void setDate(Date date) {
  this.date = date;
 }

}
Valter Silva
quelle
Zu Ihrer Information: Ab Gson 1.7 ist der Konstruktor no-args nicht mehr erforderlich. Siehe groups.google.com/group/google-gson/browse_thread/thread/… Viel Spaß beim Codieren.
Joel

Antworten:

328

Mit Gson müssten Sie nur Folgendes tun:

List<Video> videos = gson.fromJson(json, new TypeToken<List<Video>>(){}.getType());

Möglicherweise müssen Sie auch einen Konstruktor ohne Argumente für die VideoKlasse angeben, für die Sie deserialisieren.

ColinD
quelle
Alter, du bist unglaublich, vielen Dank, es funktioniert. Mein Fehler war, keinen Konstruktor ohne Argumente zu erstellen. Ich danke dir sehr!
Valter Silva
4
Was ist das {} in der Klausel new TypeToken <List <Video >> () {}. GetType ()? Wie ist die legale Java-Syntax?
Maxim Veksler
8
@Maxim: Es wird eine anonyme Unterklasse von TypeToken<List<Video>>... erstellt. Dies ist ein Trick, mit dem der resultierende Typ dargestellt werden kann List<Video>, da Unterklassen vollständig spezifizierter generischer Typen die generischen Typinformationen beibehalten.
ColinD
1
Die 2.1-Version von Gson verfügt jetzt über einen Standardzugriffskonstruktor. Daher können wir den obigen Code nicht verwenden. Stattdessen verfügt die TypeToken-Klasse jetzt über die folgende Methode: public static TypeToken <?> Get (Type type) {return new TypeToken (Typ); } Aber in diesem Fall ... wie könnten wir den richtigen Typ dafür angeben ???
Pablo
1
@Pablo: Es sieht für mich so aus, als ob der No- Arg -Konstruktor für TypeTokenimmer noch protectedin Gson 2.1 ist, also sollte das Obige immer noch funktionieren.
ColinD
108

Eine andere Möglichkeit besteht darin, ein Array als Typ zu verwenden, z.

Video[] videoArray = gson.fromJson(json, Video[].class);

Auf diese Weise vermeiden Sie den Ärger mit dem Type-Objekt. Wenn Sie wirklich eine Liste benötigen, können Sie das Array jederzeit in eine Liste konvertieren, z.

List<Video> videoList = Arrays.asList(videoArray);

IMHO ist dies viel besser lesbar.


In Kotlin sieht das so aus:

Gson().fromJson(jsonString, Array<Video>::class.java)

Verwenden Sie einfach die .toList()Methode, um dieses Array in List zu konvertieren

DevNG
quelle
1
Die akzeptierte Antwort ist gut, aber ich bevorzuge dies, da alles, was ich wirklich wollte, eine Liste von Sachen ist und das Array ausreicht, um als "Liste von Sachen" zu dienen
smac89
10

Probieren Sie diesen Einzeiler

List<Video> videos = Arrays.asList(new Gson().fromJson(json, Video[].class));

Warnung: Die von videoszurückgegebene Liste Arrays.asListist unveränderlich - Sie können keine neuen Werte einfügen.


Referenz:

  1. Methodenarrays # asList
  2. Konstrukteur Gson
  3. Verfahren Gson # fromJson (Quelle jsondes Typs sein kann JsonElement, Readeroder String)
  4. Interface - Liste
  5. JLS - Arrays
  6. JLS - Generische Schnittstellen
naXa
quelle
2

Seien Sie vorsichtig mit der Antwort von @DevNG. Arrays.asList () gibt die interne Implementierung von ArrayList zurück, die einige nützliche Methoden wie add (), delete () usw. nicht implementiert. Wenn Sie sie aufrufen, wird eine UnsupportedOperationException ausgelöst. Um eine echte ArrayList-Instanz zu erhalten, müssen Sie Folgendes schreiben:

List<Video> = new ArrayList<>(Arrays.asList(videoArray));
Bogdan Kornev
quelle
wat? Arrays.asList gibt eine List-Schnittstelle zurück, die auch add () und remove () bereitstellt!
Enrichman
2
@Enrichman: Arrays.asList () gibt eine Liste mit fester Größe zurück, die vom angegebenen Array unterstützt wird. Diese ArrayList-Implementierung erweitert eine Klasse AbstractList und überschreibt nicht die Methode remove (int index) aus der Basisklasse. Und wenn Sie sich den Quellcode von AbstractList.remove (int index) ansehen, werden Sie feststellen, dass immer UnsupportedOperationException ausgelöst wird. Gleiches gilt für die Methode add ().
Bogdan Kornev
1
Wo, das ist ziemlich hässlich, das wusste ich nicht. Vielen Dank für den Hinweis. :)
Enrichman