8

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);
}
lvr123
  • 524
  • 6
  • 24
  • http://stackoverflow.com/q/36964995/1032167 more info. Create custom `class PathConverter implements JsonDeserializer, JsonSerializer` and register it as `.registerTypeHierarchyAdapter(Path.class, new MyPathConverter())` – varren May 01 '16 at 12:45

2 Answers2

3

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.

Douglas
  • 5,017
  • 1
  • 14
  • 28
  • 1
    I understand that. But in the same time, this class is a core Java class since Java 7 and should be handled correctly by Gson. I don't find it sound that every developer must implement his own serializer/deserializer for this class. This should be a core feature of Gson. – lvr123 Feb 19 '16 at 10:18
  • 1
    @lvr123 It doesn't implement `Serializable` and its purpose is mostly to parse, validate, manipulate, and otherwise use data, not to store it. Neither Gson nor any other serialization library has a good reason to give it special handling because serialization is not what `Path` is for. Map and the many subinterfaces of Collection have data storage as their primary purpose, and Gson does have special handling for those. – Douglas Feb 19 '16 at 16:42
  • 2
    What do you propose to serialize this type of Object ? – lvr123 Apr 14 '16 at 09:33
0

You can either use ExclusionStrategy to exclude certain types of classes or you can use GsonBuilder.registerTypeAdapter to implement custom serialization/deserialization.
check out the docs

Amirhosein Al
  • 470
  • 6
  • 18