2013-02-03 25 views
5

Tôi có một bản đồ nơi giá trị của một khóa là danh sách các đối tượng. Có thể tuần tự hóa các khóa thông qua builder.enableComplexMapKeySerialization(); nhưng các giá trị không được tuần tự hóa như mong đợi bởi vì chúng trả về một chuỗi trên deserialization thay vì đối tượng.Gson Nối tiếp HashMap <Giáo viên, Danh sách <Student>>

Dưới đây là sản phẩm của serialization

[{ "id": 31001, "tên": Giáo viên "]}, // Đây là chìa khóa

[{" id ": 33033 , "tên": "student1"}, { "id": 34.001, "tên": "student2"}]], // Đây là danh sách các giá trị

tôi đã sử dụng TypeToken có liên quan mà là TypeToken<HashMap<Teacher, List<Student>>> nhưng vẫn các giá trị danh sách được trả về một chuỗi trên deserialization thay vì đối tượng.

Trả lời

17

JSON được tạo thành từ các cặp tên/giá trị (trong đó bên giá trị có thể là danh sách các thứ). Phần tên trong số đó là một chuỗi (Xem: http://json.org)

Điều bạn đang cố gắng làm là sử dụng một đối tượng làm tên; bạn không thể làm điều đó trực tiếp. Đối tượng JSON không thể là tên cho cặp tên/giá trị.

Nếu bạn đọc documentation for enableComplexMapKeySerialization, nó giải thích kết quả JSON sẽ là gì.

JSON nó tạo ra (một Bản đồ dưới dạng một mảng JSON) sẽ deserialize hoàn toàn trở lại bản đồ của bạn. Sau đây là một ví dụ hoàn chỉnh, hoạt động (Java 7).

Lưu ý rằng khi tôi deserialize từ JSON trở lại Java, tôi đang iterating trên bản đồ để có được các phím. Điều này là do không có equals()hashCode() bị ghi đè trong Teacher không có cách nào để tạo một phiên bản mới Teacher và làm cho nó hoạt động như một khóa (chỉ các giá trị tham chiếu được so sánh).

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.reflect.TypeToken; 
import java.lang.reflect.Type; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 


public class App 
{ 
    public static void main(String[] args) 
    { 
     HashMap<Teacher, List<Student>> map = new HashMap<>(); 
     Teacher t = new Teacher("12345", "Teacher"); 
     Teacher t2 = new Teacher("23456", "Teacher2"); 
     ArrayList<Student> list = new ArrayList<>(); 
     for (int i = 0; i < 3; i++) { 
      list.add(new Student(String.valueOf(i), "Student" + String.valueOf(i))); 
     } 

     map.put(t, list); 
     map.put(t2, list); 

     GsonBuilder builder = new GsonBuilder(); 

     Gson gson = 
      builder.enableComplexMapKeySerialization().setPrettyPrinting().create(); 
     Type type = new TypeToken<HashMap<Teacher,List<Student>>>(){}.getType(); 
     String json = gson.toJson(map, type); 
     System.out.println(json); 

     System.out.println("\nAfter deserialization:"); 
     HashMap<Teacher, List<Student>> map2 = gson.fromJson(json, type); 

     for (Teacher t3 : map2.keySet()) { 
      System.out.println(t3.name); 
      for (Student s2 : map2.get(t3)) { 
       System.out.println("\t" + s2.name); 
      } 
     } 
    } 
} 

class Teacher { 
    public String id; 
    public String name; 

    public Teacher(String id, String name) { 
     this.id = id; 
     this.name = name; 
    } 
} 

class Student { 
    public String id; 
    public String name; 

    public Student(String id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

} 

Output:

[ 
    [ 
    { 
     "id": "12345", 
     "name": "Teacher" 
    }, 
    [ 
     { 
     "id": "0", 
     "name": "Student0" 
     }, 
     { 
     "id": "1", 
     "name": "Student1" 
     }, 
     { 
     "id": "2", 
     "name": "Student2" 
     } 
    ] 
    ], 
    [ 
    { 
     "id": "23456", 
     "name": "Teacher2" 
    }, 
    [ 
     { 
     "id": "0", 
     "name": "Student0" 
     }, 
     { 
     "id": "1", 
     "name": "Student1" 
     }, 
     { 
     "id": "2", 
     "name": "Student2" 
     } 
    ] 
    ] 
] 

After deserialization: 
Teacher2 
    Student0 
    Student1 
    Student2 
Teacher 
    Student0 
    Student1 
    Student2 

Nếu bạn thực hiện equals()hashCode() trong lớp Teacher của bạn, sau đó bạn sẽ có thể sử dụng một trường hợp mới của Teacher để lấy mọi thứ từ bản đồ:

class Teacher { 

    public String id; 
    public String name; 

    public Teacher(String id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    @Override 
    public int hashCode() 
    { 
     int hash = 3; 
     hash = 37 * hash + Objects.hashCode(this.id); 
     hash = 37 * hash + Objects.hashCode(this.name); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object obj) 
    { 
     if (obj == null) 
     { 
      return false; 
     } 
     if (getClass() != obj.getClass()) 
     { 
      return false; 
     } 
     final Teacher other = (Teacher) obj; 
     if (!Objects.equals(this.id, other.id)) 
     { 
      return false; 
     } 
     if (!Objects.equals(this.name, other.name)) 
     { 
      return false; 
     } 
     return true; 
    } 

} 

Khi bạn có điều đó, bạn có thể làm:

... 
HashMap<Teacher, List<Student>> map2 = gson.fromJson(json, type); 
Teacher t = new Teacher("23456", "Teacher2"); 
List<Student> list = map2.get(t); 
... 
+1

cảm ơn bạn đã hướng dẫn giải quyết vấn đề – bobo

+1

Cảm ơn, tôi đã sử dụng giải pháp này, nhưng hãy cẩn thận với ClassNotFoundException trên enableComplexMapKeySerialization trên một số thiết bị/phiên bản HTC (HTC đã quyết định bao gồm gson, và nó là phiên bản cũ, cũng ghi đè phiên bản được bao gồm trong ứng dụng của bạn). – zilinx

+2

Giải thích đáng yêu !! Tôi đã không nhận thức được ** enableComplexMapKeySerialization ** – Leeeeeeelo

Các vấn đề liên quan