Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gson: serializing a java.nio.Path causes a StackOverflowError

Serializing this, causes a 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\\");
    }
}

It looks like a bug to me ! Or I'm doing something wrong ? Is there workaround (expect writing some custom serializer that converts the path to 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)
    ...

Serializing method is:

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);
}
like image 474
lvr123 Avatar asked Feb 18 '16 22:02

lvr123


1 Answers

Examine the object returned by Paths.get("c:\\temp\\"); in a debugger. On my machine, it has a field named fs that contains a WindowsFileSystem. This, in turn, has a field provider that contains a WindowsFileSystemProvider - and provider has a field theFileSystem which contains the same WindowsFileSystem as the original fs field does. Voila, cyclic reference.

Gson uses reflection to inspect and serialize, recursively, every non-transient field in the object you give it. A cyclic reference like this sends it into infinite recursion, which ends in StackOverflowError. To fix this, you will need to either implement custom serialization or serialize a specific property of the Path rather than the whole object. Marking any or all of the fields involved in the cycle as transient would also work, but that would require write access to the library's code.

like image 182
Douglas Avatar answered Nov 15 '22 07:11

Douglas