如何使用 GSON 或 Java 中的其他 JSON 库反序列化列表?

Posted

技术标签:

【中文标题】如何使用 GSON 或 Java 中的其他 JSON 库反序列化列表?【英文标题】:How to deserialize a list using GSON or another JSON library in Java? 【发布时间】:2011-05-18 03:15:44 【问题描述】:

我可以在 GAE 上的 servlet 中序列化 List<Video>,但无法反序列化它。我做错了什么?

这是我在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;
 


【问题讨论】:

仅供参考,从 Gson 1.7 开始,不再需要无参数构造函数。见groups.google.com/group/google-gson/browse_thread/thread/…快乐编码。 【参考方案1】:

使用 Gson,您只需要执行以下操作:

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

您可能还需要在要反序列化的 Video 类上提供无参数构造函数。

【讨论】:

老兄,你太棒了,非常感谢,它有效。我的错误是没有创建一个没有参数的构造函数。非常感谢! new TypeToken>().getType() 子句中的 是什么?合法的java语法如何? @Maxim:它正在创建TypeToken&lt;List&lt;Video&gt;&gt; 的匿名子类......这是一个允许结果类型表示List&lt;Video&gt; 的技巧,因为完全指定的泛型类型的子类保留了泛型类型信息。 2.1 版本的 Gson 现在有一个默认的访问构造函数......因此我们不能使用上面的代码......现在 TypeToken 类有以下方法: public static TypeToken> get(Type type) return new TypeToken(type);但在这种情况下......我们如何才能为其提供正确的类型??? @Pablo:在我看来,TypeToken 的无参数构造函数在 Gson 2.1 中仍然是 protected,所以上述方法应该仍然有效。【参考方案2】:

另一种方法是使用数组作为类型,例如:

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

这样你就避免了使用 Type 对象的所有麻烦,如果你真的需要一个列表,你可以随时将数组转换为列表,例如:

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

恕我直言,这更具可读性。


Kotlin 中如下所示:

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

要将这个数组转换成List,只需使用.toList()方法

【讨论】:

公认的答案很好,但我更喜欢这个,因为我真正想要的是一个东西列表,而数组足以充当“东西列表”【参考方案3】:

我推荐这个单线

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

警告:Arrays.asList 返回的videos 列表是不可变的 - 您不能插入新值。如果需要修改,请在new ArrayList&lt;&gt;(...)中换行。


参考:

    方法Arrays#asList 构造函数Gson 方法Gson#fromJson(源json可能是JsonElementReaderString类型) 接口List JLS - Arrays JLS - Generic Interfaces

【讨论】:

【参考方案4】:

小心使用@DevNG 提供的答案。 Arrays.asList() 返回 ArrayList 的内部实现,它没有实现一些有用的方法,如 add()、delete() 等。如果调用它们,则会抛出 UnsupportedOperationException。 为了获得真正的 ArrayList 实例,您需要编写如下内容:

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

【讨论】:

什么? Arrays.asList 返回一个 List 接口,同时提供 add() 和 remove()! @Enrichman:Arrays.asList() 返回由指定数组支持的固定大小列表。此 ArrayList 实现扩展了一个类 AbstractList 并且不覆盖基类中的方法 remove(int index)。如果您查看 AbstractList.remove(int index) 的源代码,您会发现它总是抛出 UnsupportedOperationException。 add() 方法也是如此。 哇,太丑了,我不知道。感谢您指出。 :)

以上是关于如何使用 GSON 或 Java 中的其他 JSON 库反序列化列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 GSON 或 android 中的任何其他库的情况下使用改造以字符串形式获得响应 [重复]

Gson关于抽象类的序列化与反序列化

如何使用 Java 和 Gson 中的构建器模式将选择类字段序列化为 JSON 字符串?

Gson——如何忽略用@Expose标记的字段

Android编程入门--开源框架Gson

Android解析json-Gson使用