Come deserializzare un elenco utilizzando GSON o un'altra libreria JSON in Java?


121

Posso serializzare un List<Video>nel mio servlet su GAE, ma non posso deserializzarlo. Che cosa sto facendo di sbagliato?

Questo è il mio video di classe in GAE, che è serializzato:

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;
 }

}

Questo è il mio video di classe nell'altra mia applicazione, dove provo a deserializzare:

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;
 }

}

Cordiali saluti, a partire da Gson 1.7, il costruttore senza argomenti non è più richiesto. Vedi groups.google.com/group/google-gson/browse_thread/thread/… Happy coding.
Joel

Risposte:


328

Con Gson, avresti solo bisogno di fare qualcosa come:

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

Potrebbe anche essere necessario fornire un costruttore senza argomenti sulla Videoclasse a cui si sta deserializzando.


Amico, sei fantastico, grazie mille, funziona. Il mio errore è stato non creare un costruttore senza argomenti. Grazie mille!
Valter Silva

4
Qual è il {} nella clausola new TypeToken <List <Video>> () {}. GetType ()? Com'è la sintassi java legale?
Maxim Veksler

8
@ Maxim: sta creando una sottoclasse anonima di TypeToken<List<Video>>... è un trucco che consente al tipo risultante di rappresentare List<Video>, poiché le sottoclassi di tipi generici completamente specificati conservano le informazioni sul tipo generico.
ColinD

1
La versione 2.1 di Gson ora ha un costruttore di accesso predefinito ... quindi non possiamo usare il codice sopra ... invece ora la classe TypeToken ha il seguente metodo: public static TypeToken <?> Get (Type type) {return new TypeToken (tipo); } Ma in questo caso ... come potremmo fornirgli il tipo corretto ???
Pablo

1
@ Pablo: Mi sembra che il costruttore senza argomenti TypeTokensia ancora protectedin Gson 2.1, quindi quanto sopra dovrebbe ancora funzionare.
ColinD

108

Un altro modo è usare un array come tipo, ad esempio:

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

In questo modo eviti tutte le seccature con l'oggetto Type e se hai davvero bisogno di un elenco puoi sempre convertire l'array in un elenco, ad esempio:

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

IMHO questo è molto più leggibile.


In Kotlin questo assomiglia a questo:

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

Per convertire questo array in List, usa semplicemente .toList()method


1
La risposta accettata è buona, ma preferisco questa poiché tutto ciò che volevo veramente è un elenco di cose e l'array è sufficiente per servire come "elenco di cose"
smac89


2

Fai attenzione quando usi la risposta fornita da @DevNG. Arrays.asList () restituisce un'implementazione interna di ArrayList che non implementa alcuni metodi utili come add (), delete (), ecc. Se li chiami, verrà generata un'eccezione UnsupportedOperationException. Per ottenere un'istanza di ArrayList reale è necessario scrivere qualcosa del genere:

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

wat? Arrays.asList restituisce un'interfaccia List, che fornisce anche add () e remove ()!
Enrichman

2
@Enrichman: Arrays.asList () restituisce un elenco di dimensioni fisse supportato dall'array specificato. Questa implementazione di ArrayList estende una classe AbstractList e non sovrascrive il metodo remove (int index) dalla classe base. E se guardi il codice sorgente di AbstractList.remove (int index) vedresti che viene sempre lanciato UnsupportedOperationException. Lo stesso vale per il metodo add ().
Bogdan Kornev,

1
Wo, è piuttosto brutto, non lo sapevo. Grazie per segnalarlo. :)
Enrichman
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.