Gson:序列化java.nio.Path会导致StackOverflowError

时间:2016-02-18 22:39:36

标签: java serialization gson

序列化,导致StackOverFlowError:

import java.nio.file.Path;
import java.nio.file.Paths;

public class Tmp{
    private Path path=null;
    public Tmp() {
        path=Paths.get("c:\\temp\\");
    }
}

对我来说这看起来像个错误!或者我做错了什么? 是否有解决方法(期望编写一些将路径转换为String的自定义序列化程序)

java.lang.StackOverflowError
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:372)

    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:381)
    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:376)
    ...
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:128)

    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:75)
    at com.google.gson.Gson.getAdapter(Gson.java:358)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getFieldAdapter(ReflectiveTypeAdapterFactory.java:109)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.access$100(ReflectiveTypeAdapterFactory.java:46)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(ReflectiveTypeAdapterFactory.java:84)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:83)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:129)
    ...

序列化方法是:

public static void saveTo(BatchLogging logging, Path path) throws IOException {
    Gson gson=new GsonBuilder().setPrettyPrinting().create();
    // String json = gson.toJson(logging);
    String json = gson.toJson(new Tmp());
    List<String> lines = Arrays.asList(json.split(System.lineSeparator()));
    Files.write(path, lines, StandardCharsets.UTF_8);
}

2 个答案:

答案 0 :(得分:3)

检查调试器中Paths.get("c:\\temp\\");返回的对象。在我的计算机上,它有一个名为fs的字段,其中包含WindowsFileSystem。反过来,这有一个包含provider的字段WindowsFileSystemProvider - provider有一个字段theFileSystem,其中包含与原始WindowsFileSystem相同的fs 1}}字段。 Voila,循环参考。

Gson使用反射来递归地检查和序列化你给它的对象中的每个非瞬态字段。像这样的循环引用将其发送到无限递归,该递归以StackOverflowError结束。要解决此问题,您需要实现自定义序列化或序列化Path的特定属性,而不是整个对象。将周期中涉及的任何或所有字段标记为transient也可以,但这需要对库的代码进行写访问。

答案 1 :(得分:0)

您可以使用 ExclusionStrategy 排除某些类型的类,也可以使用 GsonBuilder.registerTypeAdapter 实现自定义序列化/反序列化。
check out the docs