2012-05-17 4 views
19

Parece que GSON está haciendo algún tipo de truco cuando mira los campos internos de mis JavaBeans en lugar de utilizar la información de propiedad de acceso público. Desafortunadamente, esto no nos volará porque nuestros granos mágicamente creados están llenos de campos privados que no quiero almacenar.GSON no llama a mi TypeAdapter para un tipo que es una interfaz

@Test 
public void testJson() throws Exception 
{ 
    Player player = new MagicPlayer(); //BeanUtils.createDefault(Player.class); 
    player.setName("Alice"); 

    Gson gson = new GsonBuilder() 
     .registerTypeAdapter(Player.class, new PlayerTypeAdapter()) 
     .create(); 

    System.out.println(gson.toJson(bean)); 
} 

private static class PlayerTypeAdapter implements JsonSerializer<Player> 
{ 
    @Override 
    public JsonElement serialize(Player player, Type type, 
           JsonSerializationContext context) 
    { 
     throw new RuntimeException("I got called, woohoo"); 
    } 
} 

public static interface Player //extends SupportsPropertyChanges 
{ 
    public String getName(); 
    public void setName(String name); 
} 

// Simple implementation simulating what we're doing. 
public static class MagicPlayer implements Player 
{ 
    private final String privateStuff = "secret"; 
    private String name; 

    @Override 
    public String getName() 
    { 
     return name; 
    } 

    @Override 
    public void setName(String name) 
    { 
     this.name = name; 
    } 
} 

Esto da:

{"privateStuff":"secret","name":"Alice"} 

Y, por supuesto, nunca llama mi adaptador tipo, lo que aparentemente hace que sea imposible conseguir cualquier otro comportamiento.

+0

Podría Agrega el código que llama a Gson.toJson()? –

+0

No está claro si este es el mismo problema, pero me encontré con algo similar hace un tiempo, quizás te ayude: http://stackoverflow.com/questions/5952595/serializing-list-of-interfaces-gson/15557654# 15557654 – dimo414

Respuesta

-1

Por qué no funciona:

  1. PlayerTypeAdapter debe implementa JsonSerializer. ¿Lo hace?

  2. Si lo hace - de lo que debería funcionar. Funciona perfecto para mí, así que no veo por qué no funciona para ti. Comience su aplicación en depuración, ponga puntos de interrupción y finalice la compra. Debería haber alguna razón.

En su prueba, ¿dónde está el constructor Gson con adaptador? Debe cambiarlo:

public void testJson() throws Exception 
{ 
    Player player = new MagicPlayer(); //BeanUtils.createDefault(Player.class); 
    player.setName("Alice"); 

    // this is wrong if you want adapter 
    /* Gson gson = new Gson(); */ 

    // this is what you nead 
    Gson gson = new GsonBuilder() 
     .registerTypeAdapter(Player.class, new PlayerTypeAdapter()) 
     .create(); 

    System.out.println(gson.toJson(bean)); 
} 
+0

Puede ver en la pregunta anterior cómo se implementa PlayerTypeAdapter. Puse un punto de interrupción en la línea donde estoy lanzando la excepción, pero nunca se alcanza la línea. Ergo, Gson no está llamando a mi serializador. Debe haber algo más que se supone que debo hacer. O eso, o Gson no llama a los adaptadores de tipo para las interfaces (lo que significa que no puedo usarlo). – Trejkaz

+0

De acuerdo, actualizado para eliminar CGLIB de la ecuación. Gson todavía no llama a mi adaptador de tipo en ningún momento. – Trejkaz

+2

Lea la pregunta antes de actualizar su respuesta. – Trejkaz

9

La versión actual de GSON no funciona de esta manera. Esto serializará su tipo usando el adaptador.

gson.toJson(bean, Player.class)

alternativa, se puede registrar el PlayerTypeAdapter para MagicPlayer.class y su código existente funcionará. GSON busca el TypeAdapter solo por el tipo concreto (o nivel superior). Por lo tanto, deberá registrar un adaptador de tipo personalizado para cada tipo concreto que pueda encontrar.

Hay TypeHeirarchyAdapter para cuando desee que se use el mismo TypeAdapter para todas las clases de extensión de un tipo determinado. Sin embargo, no he tenido buena suerte con esto y realmente no he dedicado tiempo a investigar por qué no me ha funcionado. Aquí está una cierta discusión relevante: https://groups.google.com/forum/?fromgroups=#!searchin/google-gson/interface/google-gson/0ebOxifqwb0/OXSCNTiLpBQJ

+0

Esto responde a la parte principal de la pregunta acerca de por qué no funciona.No resuelve exactamente el problema ni hace que GSON se pueda usar de ninguna manera, porque confiar en el código para decirle que el tipo de todo nunca va a funcionar. Por ejemplo, hay otro lugar donde tengo una lista donde cada objeto podría ser de cualquier tipo. Ahora que se supone que debo hacer? – Trejkaz

+0

La segunda parte de la pregunta explica qué hacer. Para cada tipo concreto, debe registrar el 'TypeAdapter' que desea usar. –

37

que tenían el mismo problema, con la versión actual de GSON (2.3.1) y tengo trabajo mediante el uso de

.registerTypeHierarchyAdapter(Player.class, new PlayerTypeAdapter()) 

en lugar de

.registerTypeAdapter(Player.class, new PlayerTypeAdapter()) 
+2

Éste debe ser aceptado como una respuesta. Funciona con java.util.Calendar (tipo real es java.util.GregorianCalendar) –

Cuestiones relacionadas