【问题标题】:Trouble with Gson serializing an ArrayList of POJO'sGson 序列化 POJO 的 ArrayList 的问题
【发布时间】:2011-04-28 03:56:03
【问题描述】:

我一直计划使用 simpleXML 来满足我的序列化需求,但我想我会尝试使用 JSON 来学习新的东西。

这是我用来尝试使用 Gson 1.7.1 序列化测试 POJO 的 ArrayList 的代码。

注意:我删除了字符串“s”的读取器/写入器以简化代码。

package test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.gson.Gson;

public class TestGsonSerialDeserialList {
    public static void main(String[] args) throws IOException{
        Gson gson = new Gson();

        //Make Serial 
        String s;
        List<TestObject> list = Collections.synchronizedList(new ArrayList<TestObject>() );
        list.add(new TestObject());
        list.add(new TestObject());

        s = gson.toJson(list, ArrayList.class);
        System.out.println(s);

        //Eat Serial
        List<TestObject> list2 = Collections.synchronizedList(gson.fromJson(s, ArrayList.class) );
        System.out.println(list2.get(0) );
        System.out.println(list2.get(1) );
    }
}

这是我得到的输出:

[{"objectID":1,"i1":12345,"name":"abcdefg","s":["a","b","c"]},{"objectID":2,"i1":12345,"name":"abcdefg","s":["a","b","c"]}]
java.lang.Object@5c74c3aa
java.lang.Object@75d9fd51

在我的新手眼中,这看起来是正确的。只是,对象的 DeSerialized 列表包含基本对象,而不是 TestObject 的 I 序列化。谁能向我解释一下,如果有的话,我可以做些什么来完成这项工作?

编辑:

更正测试:感谢 ColinD

package test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class TestGsonSerialDeserialList {
    public static void main(String[] args) throws IOException{
        System.out.println("--- Serialize / Deserialize Started ---");
        String fileName = "json\\testList.json";

        Gson gson = new Gson();
        Type listOfTestObject = new TypeToken<List<TestObject>>(){}.getType();

        //Make Serial 
        Writer osWriter = new OutputStreamWriter( new FileOutputStream(fileName));
        List<TestObject> list = Collections.synchronizedList(new ArrayList<TestObject>() );
        list.add(new TestObject());
        list.add(new TestObject());
        list.add(new TestObject());
        list.add(new TestObject());
        gson.toJson(list, osWriter);
        osWriter.close();


        //Eat Serial
        Reader isReader = new InputStreamReader( new FileInputStream((fileName) ) );
        List<TestObject> list2 = Collections.synchronizedList(
            (List<TestObject>)gson.fromJson(isReader, listOfTestObject) 
        );
        isReader.close();
        System.out.println(list2.get(0) );
        System.out.println(list2.get(1) );
        System.out.println(list2.get(2) );
        System.out.println(list2.get(3) );
        System.out.println("--- Serialize / Deserialize Ended ---");
    }
}

输出:

--- Serialize / Deserialize Started ---
ID#: 1, i1: 12345, name: abcdefg, s[]: [Ljava.lang.String;@95c083
ID#: 2, i1: 12345, name: abcdefg, s[]: [Ljava.lang.String;@6791d8c1
ID#: 3, i1: 12345, name: abcdefg, s[]: [Ljava.lang.String;@182d9c06
ID#: 4, i1: 12345, name: abcdefg, s[]: [Ljava.lang.String;@5a5e5a50
--- Serialize / Deserialize Ended ---

EDIT2:

老实说,我不知道为什么,但是当我将 TestObject 中嵌入的简单 String[] 替换为 ArrayList 时,它开始正确序列化。

--- Serialize / Deserialize Started ---
ID#: 1, i1: 12345, name: abcdefg, s[]: [a, b, c]
ID#: 2, i1: 12345, name: abcdefg, s[]: [a, b, c]
ID#: 3, i1: 12345, name: abcdefg, s[]: [a, b, c]
ID#: 4, i1: 12345, name: abcdefg, s[]: [a, b, c]
--- Serialize / Deserialize Ended ---

【问题讨论】:

  • 旁注:摆脱 Collections.synchronizedList() 调用。你有一个单线程场景,这些调用只会增加开销,没有别的
  • 你是对的。他们在那里确保我可以让它工作。一旦它工作,我将删除它们。这纯粹是出于教育原因。一旦我对 Json 序列化有了很好的了解,我就会开始构建以供实际使用。
  • 话虽如此,谁能指出我在哪里可以弄清楚如何使用 TypeToken 反序列化对象嵌入数组?
  • 好吧,看来用 ArrayList 替换 String[] 解决了问题。

标签: java json serialization arraylist gson


【解决方案1】:

您需要向 Gson 提供有关您正在使用的 List 的特定泛型类型(或与它一起使用的任何泛型类型)的信息。特别是在反序列化 JSON 时,它需要这些信息来确定应该将每个数组元素反序列化为哪种类型的对象。

Type listOfTestObject = new TypeToken<List<TestObject>>(){}.getType();
String s = gson.toJson(list, listOfTestObject);
List<TestObject> list2 = gson.fromJson(s, listOfTestObject);

这在Gson user guide 中有记录。

【讨论】:

  • 我担心我没有看到明显的东西。我以前从未使用过 Type,并且对它的使用感到困惑。你刚刚为我清理了它。非常感谢。
  • 我可能很快就会有另一个关于队列序列化的问题!希望你不要介意。
  • 我有点快。看来我需要找到一种方法将 TypeToken 应用于 TestObject 的 String[]。
  • @ColinD 如果List&lt;TestObject&gt; 嵌套在另一个类中怎么办?在这种情况下如何使用Type 来反序列化使用MyCustomClass obj = gson.fromJson(json, MyCustomClass.class)
  • @raffian:你的意思是如果MyCustomClass 有一个需要反序列化的List&lt;TestObject&gt; 字段?如果是这样就没有问题了……Gson可以静态看到该字段的类型为List&lt;TestObject&gt;,并据此反序列化列表。
猜你喜欢
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
相关资源
最近更新 更多