我有这些课程:
class A implements Composite
{
Composite b = new B();
}
class B implements Composite
{
}
interface Composite
{
}
基本上A
由B
组成,我想将它们保存在文件中。
在活动中我这样做:
String filename = "myfile.txt";
A a = new A();
Gson gson = new Gson();
String s = son.toJson(a);
FileOutputStream outputStream;
try
{
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(s.getBytes);
outputStream.close();
}
catch(Exception e)
{
}
然后我用这段代码来阅读:
FileInputStream fileInputStream = null;
try
{
fileInputStream = openFileInput(filename);
}
catch(FileNotFoundException e)
{}
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream)l;
BufferReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder stringBuilder = new StringBuilder();
String line;
try
{
while((line = bufferedReader.readLine()) != null)
{
stringBuilder.append(line);
}
}
catch(IOException e)
{
}
String json = stringBuilder.toString();
Gson gson2 = new Gson();
// Exception here.
A a2 = gson2.fromJson(json, A.class);
问题在于A类中的对象B.Gson似乎并不知道B
的类型。所以我得到了这个例外:
JNI在应用程序中检测到错误:无法创建类型的对象 复合
答案 0 :(得分:2)
原因应该是Gson在A中看到和接口,而不是类。如果我没有弄错的话,Gson使用编译时信息(即变量的数据类型)而不是运行时信息(即包含B类对象的变量)。
如果您将类更改为以下内容,则应将其序列化为正确:
class A implements Composite
{
B b = new B();
}
class B implements Composite
{
}
interface Composite
{
}
答案 1 :(得分:1)
问题是接口没有属性,因此您需要序列化实现该接口的类。您需要使用构建器
创建Gson实例GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Composite.class, new CompositeAdapter());
Gson gson = builder.create();
并定义序列化Composite实例的代码
public static class CompositeAdapter implements JsonSerializer<Composite>, JsonDeserializer<Composite> {
private static final String CLASSNAME = "CLASSNAME";
private static final String DATA = "DATA";
public Composite deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jsonObject = jsonElement.getAsJsonObject();
JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
String className = prim.getAsString();
Class klass = null;
try {
klass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
// TODO: handle somehow
}
return jsonDeserializationContext.deserialize(jsonObject.get(DATA), klass);
}
public JsonElement serialize(Composite jsonElement, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(CLASSNAME, jsonElement.getClass().getName());
jsonObject.add(DATA, jsonSerializationContext.serialize(jsonElement));
return jsonObject;
}
}
基本上当它序列化一个Composite实例时,它也会将类名与属性一起存储,并且在反序列化它时会创建一个实际类的实例(比如说B)。这样你不必担心为每个实现Composite的类创建一个序列化器和反序列化器,但是如果你改变了类的名称(全名,包括包名),它就不能反序列化