Gson麻烦将POJO的ArrayList序列化


71

我一直在计划使用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

在我的新手看来,这看起来是正确的。仅,反序列化的对象列表包含基本对象,而不是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 ---

编辑2:

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

--- 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()调用。您有一个单线程方案,这些调用只会增加开销,别无其他
Sean Patrick Floyd

你是对的。他们在那里确保我可以正常工作。一旦工作,我将其删除。这纯粹是出于教育原因。一旦我对Json序列化有了一个好主意,我将开始为实际使用而构建。
RogueDeus

话虽如此,谁能指出我在哪里可以弄清楚如何使用TypeToken对Object嵌入式数组进行反序列化?
RogueDeus

好吧,似乎将Array []替换为ArrayList可以解决此问题。
RogueDeus 2011年

Answers:


170

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

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

这在Gson用户指南中有所记录。


我担心自己看不到明显的东西。我以前从未使用过Type,并且对它的使用感到困惑。你刚刚帮我清理了 非常感谢你。
RogueDeus 2011年

1
关于队列的序列化,我可能很快就会有另一个问题!希望你不要介意。
RogueDeus 2011年

我在那里很快。看来我需要找到一种将TypeToken应用于TestObject的String []的方法。
RogueDeus 2011年

2
@ColinD如果List<TestObject>嵌套在另一个类中怎么办?Type在这种情况下,如何使用MyCustomClass obj = gson.fromJson(json, MyCustomClass.class)
app

1
@raffian:您的意思是是否MyCustomClassList<TestObject>需要反序列化的字段?如果是这样,那没有问题... Gson可以看到字段的类型是List<TestObject>静态的,并根据该字段反序列化列表。
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.