วิธีการแยกรายการโดยใช้ GSON หรือไลบรารี JSON อื่นใน Java


121

ฉันสามารถทำให้ไฟล์ List<Video>ใน servlet ของฉันบน 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;
 }

}

นี่คือวิดีโอสำหรับชั้นเรียนของฉันในแอปพลิเคชันอื่นของฉันซึ่งฉันพยายามที่จะ 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 ใน Gson 1.7 ไม่จำเป็นต้องใช้ตัวสร้าง no-args อีกต่อไป ดูgroups.google.com/group/google-gson/browse_thread/thread/…ขอให้สนุกกับการเขียนโค้ด
Joel

คำตอบ:


328

ด้วย Gson คุณเพียงแค่ต้องทำสิ่งต่อไปนี้

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

คุณอาจต้องจัดเตรียมคอนสตรัคเตอร์ที่ไม่มีอาร์กิวเมนต์ในVideoคลาสที่คุณกำลังแยกส่วน


เพื่อนคุณสุดยอดมากขอบคุณมากมันได้ผล ความผิดพลาดของฉันไม่ใช่การสร้างตัวสร้างที่ไม่มีอาร์กิวเมนต์ ขอบคุณมาก!
Valter Silva

4
อะไรคือ {} ในประโยคใหม่ TypeToken <List <Video>> () {}. getType ()? ไวยากรณ์จาวาถูกกฎหมายอย่างไร
Maxim Veksler

8
@ Maxim: กำลังสร้างคลาสย่อยที่ไม่ระบุตัวตนของTypeToken<List<Video>>... เป็นเคล็ดลับที่อนุญาตให้ประเภทผลลัพธ์เป็นตัวแทนList<Video>เนื่องจากคลาสย่อยของประเภททั่วไปที่ระบุอย่างครบถ้วนจะเก็บข้อมูลประเภททั่วไปไว้
ColinD

1
ตอนนี้ Gson เวอร์ชัน 2.1 มีตัวสร้างการเข้าถึงเริ่มต้นแล้ว ... ดังนั้นเราจึงไม่สามารถใช้โค้ดด้านบนได้ ... ตอนนี้คลาส TypeToken มีวิธีการต่อไปนี้: TypeToken แบบคงที่สาธารณะ <?> get (Type type) {return new TypeToken (ชนิด); } แต่ในกรณีนี้ ... เราจะระบุประเภทที่ถูกต้องได้อย่างไร ???
Pablo

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

IMHO นี่อ่านง่ายกว่ามาก


ใน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อาจเป็นชนิด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 ส่งคืนอินเทอร์เฟซรายการที่ให้ add () และ remove () ด้วย!
Enrichman

2
@Enrichman: Arrays.asList () ส่งคืนรายการขนาดคงที่ที่สนับสนุนโดยอาร์เรย์ที่ระบุ การใช้งาน ArrayList นี้ขยายคลาส AbstractList และไม่ได้แทนที่เมธอด remove (int index) จากคลาสพื้นฐาน และถ้าคุณดูซอร์สโค้ดของ AbstractList.remove (ดัชนี int) คุณจะเห็นว่า UnsupportedOperationException เสมอ เช่นเดียวกับวิธีการเพิ่ม ()
Bogdan Kornev

1
ว้าวน่าเกลียดมากฉันไม่รู้ ขอบคุณที่ชี้ให้เห็น :)
Enrichman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.