我有这些课:

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在应用程序中检测到错误:无法使类型的对象
  综合

最佳答案

问题在于接口没有属性,因此您需要序列化实现该接口的类。您需要使用构建器创建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的每个类创建序列化器和反序列化器,但是如果您更改类的名称(全名,包括程序包名称),将无法对其进行反序列化

10-05 21:16
查看更多