JavaでGSONまたは別のJSONライブラリを使用してリストを逆シリアル化する方法は?


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

}

参考までに、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逆シリアル化するクラスに引数なしのコンストラクターを提供する必要がある場合もあります。


おい、あなたは素晴らしいです、本当にありがとう、それはうまくいきます。私の間違いは、引数のないコンストラクタを作成することではありませんでした。どうもありがとうございます!
Valter Silva 2010

4
句new TypeToken <List <Video >>(){}。getType()の{}は何ですか?どのようにそれは合法的なJava構文ですか?
Maxim Veksler

8
@Maxim:完全に指定されたジェネリック型のサブクラスはジェネリック型情報を保持するので、TypeToken<List<Video>>...の匿名サブクラスを作成しています...結果の型を表すことを可能にするトリックですList<Video>
ColinD

1
Gsonの2.1バージョンには、デフォルトのアクセスコンストラクターがあります。したがって、上記のコードは使用できません。代わりに、TypeTokenクラスに次のメソッドがあります。public static TypeToken <?> get(Type type){return new TypeToken(type); }しかし、この場合はどうすれば正しいタイプを提供できますか???
パブロ

1
@Pablo:引数なしのコンストラクタTypeTokenはまだprotectedGson 2.1にあるように見えるので、上記はまだ機能するはずです。
ColinD 2012

108

別の方法は、配列を型として使用することです。例:

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

このようにして、Typeオブジェクトのすべての面倒を回避し、本当にリストが必要な場合は、常に配列をリストに変換できます。例:

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

私見これはもっと読みやすいです。


Kotlinこのように、このルックス:

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型であってもよいJsonElementReaderまたはString
  4. インターフェースリスト
  5. JLS-配列
  6. JLS-汎用インターフェース

2

@DevNGが提供する回答の使用には注意してください。Arrays.asList()は、add()、delete()などの便利なメソッドを実装していないArrayListの内部実装を返します。それらを呼び出すと、UnsupportedOperationExceptionがスローされます。実際のArrayListインスタンスを取得するには、次のように記述する必要があります。

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

ワット?Arrays.asListは、add()およびremove()も提供するListインターフェースを返します。
エンリッチマン2016

2
@Enrichman:Arrays.asList()は、指定された配列に基づく固定サイズのリストを返します。このArrayList実装は、クラスAbstractListを拡張し、基本クラスのメソッドremove(int index)をオーバーライドしません。また、AbstractList.remove(int index)のソースコードを見ると、常にUnsupportedOperationExceptionがスローされていることがわかります。add()メソッドも同様です。
Bogdan Kornev

1
Wo、それはかなり醜いです、私はそれを知りませんでした。指摘してくれてありがとう。:)
エンリッチマン2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.