Як десаріалізувати список за допомогою GSON або іншої бібліотеки JSON на Java?


121

Я можу серіалізувати List<Video>сервер у GAE, але не можу його деаріалізувати. Що я роблю неправильно?

Це моє відео в GAE, яке серіалізується:

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

}

Це відео мого класу в іншій моїй програмі, де я намагаюся десаріалізувати:

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

}

FYI, станом на Gson 1.7 конструктор без дужок більше не потрібен. Див. Groups.google.com/group/google-gson/browse_thread/thread/… Щасливе кодування.
Джоель

Відповіді:


328

З Gson вам просто потрібно буде зробити щось на кшталт:

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

Вам також може знадобитися надати конструктор без аргументу для Videoкласу, до якого ви десаріалізуєте.


Чувак, ти дивовижний, дуже дякую, це працює. Моя помилка - не створити конструктор без аргументів. Дуже дякую!
Вальтер Сільва

4
Що таке {} у пункті new TypeToken <Список <Відео>> () {}. GetType ()? Як це законний синтаксис java?
Максим Векслер

8
@Maxim: Створення анонімного підкласу з TypeToken<List<Video>>... це трюк, який дозволяє представити отриманий тип List<Video>, оскільки підкласи повністю визначених загальних типів зберігають інформацію про загальний тип.
ColinD

1
Версія 2.1 Gson тепер має конструктор доступу за замовчуванням ... отже, ми не можемо використовувати код вище ... замість цього тепер для класу TypeToken є такий метод: public static TypeToken <?> Get (type type) {return new TypeToken (тип); } Але в цьому випадку ... як ми могли надати йому правильний тип ???
Пабло

1
@Pablo: Мені здається, що конструктор no-arg TypeTokenвсе ще protectedзнаходиться в Gson 2.1, тому вищезгадане все одно має працювати.
ColinD

108

Інший спосіб - використовувати масив як тип, наприклад:

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

Таким чином ви уникнете всіх клопотів з об’єктом Type, і якщо вам справді потрібен список, ви завжди можете перетворити масив у список, наприклад:

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

ІМХО це набагато читабельніше.


У Котліні це виглядає приблизно так:

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

Щоб перетворити цей масив у Список, просто використовуйте .toList()метод


1
Прийнята відповідь хороша, але я вважаю за краще це, оскільки все, що мені дуже хотілося, - це список матеріалів і масиву, достатній для того, щоб слугувати "списком матеріалів"
smac89

10

Спробуйте цей однолінійний

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

Попередження: список videos, повернутий Arrays.asListнепорушним, ви не можете вставляти нові значення.


Довідка:

  1. Масиви методів # asList
  2. Конструктор Gson
  3. Метод Gson # fromJson (джерело jsonможе бути типу JsonElement, Readerабо String)
  4. Список інтерфейсів
  5. JLS - масиви
  6. JLS - Універсальні інтерфейси

2

Будьте обережні, використовуючи відповідь, яку надає @DevNG. Arrays.asList () повертає внутрішню реалізацію ArrayList, яка не реалізує корисні методи, такі як add (), delete () тощо. Якщо ви називатимете їх, UnsupportedOperationException буде кинуто. Щоб отримати справжній екземпляр ArrayList, вам потрібно написати щось подібне:

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

ват? Arrays.asList повертає інтерфейс списку, який забезпечує також додавання () та видалення ()!
Enrichman

2
@Enrichman: Arrays.asList () повертає список фіксованого розміру, підкріплений вказаним масивом. Ця реалізація ArrayList розширює клас AbstractList і не перекриває метод видалення (int index) з базового класу. І якщо ви подивитеся на вихідний код AbstractList.remove (int index), ви побачите, що він завжди кидається UnsupportedOperationException. Те саме стосується методу add ().
Богдан Корнєв

1
О, це дуже потворно, я цього не знав. Дякуємо, що вказали на це. :)
Енріхман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.