Bagaimana cara deserialize daftar menggunakan GSON atau perpustakaan JSON lain di Java?

121

Saya bisa membuat serial List<Video>di servlet saya di GAE, tapi saya tidak bisa menghilangkannya. Apa yang saya lakukan salah?

Ini adalah video kelas saya di GAE, yang berseri:

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

}

Ini adalah kelas saya Video di aplikasi saya yang lain, di mana saya mencoba untuk menghilangkan:

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
sumber
FYI, Sejak Gson 1.7, konstruktor no-args tidak lagi diperlukan. Lihat groups.google.com/group/google-gson/browse_thread/thread/… Selamat membuat kode.
Yoel

Jawaban:

328

Dengan Gson, Anda hanya perlu melakukan sesuatu seperti:

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

Anda mungkin juga perlu menyediakan konstruktor tanpa argumen pada Videokelas yang Anda deserialisasi.

ColinD
sumber
Bung, kamu luar biasa, terima kasih banyak, itu berhasil. Kesalahan saya tidak membuat konstruktor tanpa argumen. Terima kasih banyak!
Valter Silva
4
Apa {} dalam klausa baru TypeToken <List <Video>> () {}. GetType ()? Bagaimana sintaks java legal?
Maxim Veksler
8
@Maxim: Ini membuat subkelas anonim TypeToken<List<Video>>... ini adalah trik yang memungkinkan tipe yang dihasilkan untuk mewakili List<Video>, karena subkelas tipe generik yang ditentukan sepenuhnya mempertahankan informasi tipe generik.
ColinD
1
Versi 2.1 Gson sekarang memiliki konstruktor akses default ... maka kita tidak dapat menggunakan kode di atas ... sebagai gantinya sekarang kelas TypeToken memiliki metode berikut: public static TypeToken <?> Get (Type type) {return new TypeToken (tipe); } Tapi dalam kasus ini ... bagaimana kita bisa memberikan tipe yang benar untuk itu ???
Pablo
1
@Pablo: Sepertinya konstruktor no-arg untuk TypeTokenmasih protecteddalam Gson 2.1, jadi hal di atas masih berfungsi.
ColinD
108

Cara lain adalah dengan menggunakan array sebagai tipe, misalnya:

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

Dengan cara ini Anda menghindari semua kerumitan dengan objek Type, dan jika Anda benar-benar membutuhkan daftar, Anda selalu dapat mengonversi array menjadi daftar, misalnya:

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

IMHO ini jauh lebih mudah dibaca.


Di Kotlin ini terlihat seperti ini:

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

Untuk mengubah array ini menjadi List, cukup gunakan .toList()metode

DevNG
sumber
1
Jawaban yang diterima bagus, tapi saya lebih suka ini karena yang saya inginkan hanyalah daftar barang dan susunan cukup untuk dijadikan "daftar barang"
smac89
10

Coba satu baris ini

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

Peringatan: daftar videos, yang dikembalikan oleh Arrays.asListtidak dapat diubah - Anda tidak dapat memasukkan nilai baru.


Referensi:

  1. Metode Array # asList
  2. Pembuat Gson
  3. Metode Gson # fromJson (sumber jsonmungkin jenis JsonElement, Readeratau String)
  4. Daftar Antarmuka
  5. JLS - Array
  6. JLS - Antarmuka Generik
naXa
sumber
2

Hati-hati menggunakan jawaban yang diberikan oleh @DevNG. Arrays.asList () mengembalikan implementasi internal ArrayList yang tidak mengimplementasikan beberapa metode berguna seperti add (), delete (), dll. Jika Anda memanggilnya, UnsupportedOperationException akan dilempar. Untuk mendapatkan instance ArrayList yang sebenarnya, Anda perlu menulis sesuatu seperti ini:

List<Video> = new ArrayList<>(Arrays.asList(videoArray));
Bogdan Kornev
sumber
wat? Arrays.asList mengembalikan antarmuka Daftar, yang menyediakan add () dan remove () juga!
Enrichman
2
@Enrichman: Arrays.asList () mengembalikan daftar ukuran tetap yang didukung oleh larik yang ditentukan. Implementasi ArrayList ini memperluas kelas AbstractList dan tidak menimpa metode remove (int index) dari kelas dasar. Dan jika Anda melihat kode sumber dari AbstractList.remove (int index) Anda akan melihatnya selalu menampilkan UnsupportedOperationException. Hal yang sama untuk metode add ().
Bogdan Kornev
1
Wo, itu sangat jelek, saya tidak tahu itu. Terima kasih telah menunjukkannya. :)
Enrichman