如何使用Gson序列化java.nio.file.Path?

14

当尝试序列化包含 java.nio.file.PathObject 时,我遇到了 java.lang.StackOverflowError

即使我这样写:

public class PathConverter implements JsonDeserializer<Path>, JsonSerializer<Path> {
    @Override
    public Path deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        return Paths.get(jsonElement.getAsString());
    }

    @Override
    public JsonElement serialize(Path path, Type type, JsonSerializationContext jsonSerializationContext) {
        return new JsonPrimitive(path.toString());
    }
}

并应用它:

    String json = new GsonBuilder()
            .registerTypeAdapter(Path.class, new PathConverter())
            .create()
            .toJson(constructorSetup, new TypeToken<ConstructorSetup>() {}.getType());

我仍然无法对此类进行序列化:

public class ConstructorSetup {

    private Path appIconMimmapDirPathOnPc;

}

堆栈跟踪:(完整信息请查看pastebin

Exception in thread "main" java.lang.StackOverflowError
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:380)
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:375)
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:380)
        ...
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:380)
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:355)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:117)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    at com.google.gson.Gson.getAdapter(Gson.java:356)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    at com.google.gson.Gson.getAdapter(Gson.java:356)
        ...
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:82)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:81)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:118)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:72)
    at com.google.gson.Gson.getAdapter(Gson.java:356)

有什么解决方案吗?


1
请同时显示StackOverflowError的堆栈跟踪信息。 - randers
为什么要对Path进行序列化? - undefined
1个回答

13

你的问题在于 Path 是一个接口。假设你使用了 Paths.get("/"),它将在我的 Windows PC 上创建类似于 WindowsPath 的实例。现在,你必须告诉 GSON 如何反序列化这种类型:

ConstructorSetup setup = new ConstructorSetup();
setup.setAppIconMimmapDirPathOnPc(Paths.get("/"));

// here we get actual class type of our Path object
Class classT = setup.getAppIconMimmapDirPathOnPc().getClass();

Gson gson = new GsonBuilder().registerTypeAdapter(classT, new MyPathConverter())

你可以选择另一种方法,即使用registerTypeHierarchyAdapter

.registerTypeHierarchyAdapter(Path.class, new MyPathConverter())

typeHierarchyAdapter的目的是覆盖当您希望所有类型的子类型具有相同表示形式的情况,这正是您在Path中的情况。


4
感谢您的清晰解释!registerTypeHierarchyAdapter是我需要的。 - Alexandr
1
什么是 MyPathConverter,它的作用是什么? - ifly6

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接