Làm cách nào để giải mã hóa danh sách bằng GSON hoặc thư viện JSON khác trong Java?


121

Tôi có thể tuần tự hóa a List<Video>trong servlet của mình trên GAE, nhưng tôi không thể giải mã hóa nó. Tôi đang làm gì sai?

Đây là Video lớp học của tôi trong GAE, được đăng nhiều kỳ:

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

}

Đây là Video lớp học của tôi trong ứng dụng khác của tôi, nơi tôi cố gắng deserialize:

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, Kể từ Gson 1.7, hàm tạo no-args không còn được yêu cầu. Xem groups.google.com/group/google-gson/browse_thread/thread/… Chúc bạn viết mã vui vẻ.
Joel

Câu trả lời:


328

Với Gson, bạn chỉ cần làm điều gì đó như:

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

Bạn cũng có thể cần cung cấp một phương thức khởi tạo no-arg trên Videolớp mà bạn đang giải mã.


Anh bạn, bạn thật tuyệt vời, cảm ơn bạn rất nhiều, nó hoạt động. Sai lầm của tôi là không tạo một hàm tạo không có args. Cảm ơn bạn rất nhiều!
Valter Silva

4
{} Trong mệnh đề new TypeToken <List <Video>> () {}. GetType () là gì? Nó là cú pháp java hợp pháp như thế nào?
Maxim Veksler

8
@Maxim: Nó đang tạo ra một lớp con ẩn danh của TypeToken<List<Video>>... đó là một thủ thuật cho phép kiểu kết quả đại diện List<Video>, vì các lớp con của các kiểu chung được chỉ định đầy đủ giữ lại thông tin kiểu chung.
ColinD

1
Phiên bản 2.1 của Gson hiện có một hàm tạo truy cập mặc định ... do đó chúng ta không thể sử dụng đoạn mã trên ... thay vào đó, lớp TypeToken có phương thức sau: public static TypeToken <?> Get (Type type) {return new TypeToken (kiểu); } Nhưng trong trường hợp này ... làm thế nào chúng tôi có thể cung cấp loại chính xác cho nó ???
Pablo

1
@Pablo: Đối với tôi, có vẻ như hàm tạo no-arg TypeTokenvẫn còn protectedtrong Gson 2.1, vì vậy phần trên vẫn hoạt động.
ColinD

108

Một cách khác là sử dụng mảng làm kiểu, ví dụ:

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

Bằng cách này, bạn tránh được tất cả những rắc rối với đối tượng Type và nếu bạn thực sự cần một danh sách, bạn luôn có thể chuyển đổi mảng thành một danh sách, ví dụ:

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

IMHO điều này dễ đọc hơn nhiều.


Trong Kotlin, nó trông như thế này:

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

Để chuyển mảng này thành Danh sách, chỉ cần sử dụng .toList()phương thức


1
Câu trả lời được chấp nhận là tốt, nhưng tôi thích điều này hơn vì tất cả những gì tôi thực sự muốn là danh sách nội dung và mảng đủ để đóng vai trò là "danh sách nội dung"
smac89 10/11/15

10

Hãy thử một lớp lót này

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

Cảnh báo: danh sách videos trả về Arrays.asListlà không thay đổi - bạn không thể chèn giá trị mới.


Tài liệu tham khảo:

  1. phương pháp Mảng # asList
  2. Constructor Gson
  3. Phương thức Gson # fromJson (nguồn jsoncó thể thuộc loại JsonElement,Reader hoặcString )
  4. Giao diện Danh sách
  5. JLS - Mảng
  6. JLS - Giao diện Chung

2

Hãy cẩn thận khi sử dụng câu trả lời do @DevNG cung cấp. Arrays.asList () trả về triển khai nội bộ của ArrayList không triển khai một số phương thức hữu ích như add (), delete (), v.v. Nếu bạn gọi chúng, một ngoại lệ UnsupportedOperationException sẽ được ném ra. Để có được cá thể ArrayList thực, bạn cần viết một cái gì đó như sau:

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

w? Arrays.asList trả về giao diện Danh sách, cung cấp thêm () và xóa ()!
Enrichman

2
@Enrichman: Arrays.asList () trả về một danh sách có kích thước cố định được hỗ trợ bởi mảng đã chỉ định. Việc triển khai ArrayList này mở rộng một lớp AbstractList và không ghi đè phương thức remove (int index) khỏi lớp cơ sở. Và nếu bạn nhìn vào mã nguồn của AbstractList.remove (int index), bạn sẽ thấy nó luôn được ném UnsupportedOperationException. Đối với phương thức add () cũng vậy.
Bogdan Kornev

1
Wo, điều đó khá xấu, tôi không biết điều đó. Cảm ơn đã chỉ ra điều đó. :)
Enrichman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.