2016-02-18 39 views
5

serializzazione di questo, provoca uno StackOverflowError:GSON: serializzare un java.nio.Path provoca una 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\\"); 
    } 
} 

Sembra un bug a me! O sto facendo qualcosa di sbagliato? C'è soluzione (si aspettano scrivendo qualche serializzatore personalizzato che converte il percorso 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) 
    ... 

metodo di serializzazione è:

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); 
} 
+0

http://stackoverflow.com/q/36964995/1032167 maggiori informazioni. Creare una classe personalizzata PathConverter implementa JsonDeserializer , JsonSerializer 'e registrarlo come' .registerTypeHierarchyAdapter (Path.class, new MyPathConverter()) ' – varren

risposta

3

esaminare l'oggetto restituito da Paths.get("c:\\temp\\"); in un debugger. Sulla mia macchina, ha un campo chiamato fs che contiene uno WindowsFileSystem. Questo, a sua volta, ha un campo provider che contiene uno WindowsFileSystemProvider - e provider ha un campo theFileSystem che contiene lo stesso WindowsFileSystem come fa il campo originale fs. Voila, riferimento ciclico.

Gson usa il riflesso per ispezionare e serializzare, in modo ricorsivo, ogni campo non transitorio dell'oggetto che gli viene assegnato. Un riferimento ciclico come questo lo invia alla ricorsione infinita, che termina con StackOverflowError. Per risolvere questo problema, è necessario implementare la serializzazione personalizzata o serializzare una proprietà specifica di Path anziché l'intero oggetto. Anche la marcatura di uno o tutti i campi coinvolti nel ciclo come transient funzionerebbe, ma ciò richiederebbe l'accesso in scrittura al codice della libreria.

+1

Lo capisco. Ma allo stesso tempo, questa classe è una classe Java principale da Java 7 e dovrebbe essere gestita correttamente da Gson. Non credo che ogni sviluppatore debba implementare il proprio serializzatore/deserializzatore per questa classe. Questa dovrebbe essere una caratteristica fondamentale di Gson. – lvr123

+1

@ lvr123 Non implementa 'Serializable' e il suo scopo è principalmente di analizzare, convalidare, manipolare e altrimenti utilizzare i dati, non per memorizzarli. Né Gson né alcuna altra libreria di serializzazione hanno una buona ragione per dargli una gestione speciale perché la serializzazione non è ciò a cui è destinato 'Path'. La mappa e le numerose sottointerfacce di Collection hanno come scopo principale l'archiviazione dei dati e Gson ha una gestione speciale per questi. – Douglas

+2

Che cosa propone di serializzare questo tipo di oggetto? – lvr123