【问题标题】:Gson Serializing HashMap<Teacher, List<Student>>Gson 序列化 HashMap<Teacher, List<Student>>
【发布时间】:2013-01-18 11:33:35
【问题描述】:

我有一个映射,其中键的值是对象列表。我能够通过builder.enableComplexMapKeySerialization(); 序列化键,但值没有按预期序列化,因为它们在反序列化时返回字符串而不是对象。

下面是序列化的输出

[{"id":31001,"name":Teacher"]}, //这是关键

[{"id":33033,"name":"student1"}, {"id":34001,"name":"student2"}]], //这是值列表

我使用了相关的 TypeToken TypeToken&lt;HashMap&lt;Teacher, List&lt;Student&gt;&gt;&gt;,但列表值在反序列化时仍然返回一个字符串而不是对象。

【问题讨论】:

    标签: android serialization deserialization gson


    【解决方案1】:

    JSON 由名称/值对组成(其中值端可以是事物列表)。其中的名称部分是一个字符串(参见:http://json.org

    您要做的是使用对象作为名称;你不能直接这样做。 JSON 对象不能是名称/值对的名称。

    如果您阅读documentation for enableComplexMapKeySerialization,它会解释生成的 JSON 将是什么。

    它生成的 JSON(作为 JSON 数组的 Map)将完美地反序列化回您的地图。以下是一个完整的工作示例 (Java 7)。

    请注意,一旦我从 JSON 反序列化回 Java,我将遍历映射以获取密钥。这是因为如果没有 equals()hashCode()Teacher 中被覆盖,则无法创建 Teacher 的新实例并将其用作键(仅比较参考值)。

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

    输出:

    [
      [
        {
          "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
    

    如果您在 Teacher 类中实现 equals()hashCode(),则可以使用 Teacher 的新实例从地图中检索内容:

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

    一旦你有了它,你就可以这样做:

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

    【讨论】:

    • 谢谢,我也使用了这个解决方案,但要注意某些 HTC 设备/版本上 enableComplexMapKeySerialization 上的 ClassNotFoundException(HTC 决定自己包含 gson,它是一个旧版本,也覆盖了您的应用程序中包含的版本)。
    • 可爱的解释!!我不知道 enableComplexMapKeySerialization
    猜你喜欢
    • 2018-03-22
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多