2011-10-21 3 views
6

ne pouvait pas penser de mieux phrasé pour cette question, mais au fond, je veux enregistrer le nom d'une classe concrète dans GSON (voir « mouvement »):désérialisation une interface GSON

{ 
    "player" : { 
     "position" : { "x" : 300, "y" : 400 }, 
     "scale" : 1, 
     "rotation" : 0, 
     "sprite" : { 
      "frames" : [ { 
       "fileName" : "data/plane.png" 
      } ], 
      "duration" : 1 
     } 
    }, 
    "movementDelay" : { "elapsed" : 0, "started" : 0, "delay" : 150 }, 
    "movement" : { "class" : "controller.TopDownGridMovement" } 
} 

C'est le classe qui contient l'interface de mouvement, je veux désérialiser:

public class PlayerController { 
    private Player player; 
    private DelayTimer movementDelay; 
    private Movement movement; 

    public PlayerController() { 
    } 

    [...] 
} 

j'ai écrit un désérialiseur personnalisé:

package gson; 

import java.lang.reflect.Type; 

import com.google.gson.JsonDeserializationContext; 
import com.google.gson.JsonDeserializer; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonObject; 
import com.google.gson.JsonParseException; 

import controller.Movement; 

public class MovementDeserialiser implements JsonDeserializer<Movement> { 

    @Override 
    public Movement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
      throws JsonParseException { 
     try { 
      JsonObject obj = (JsonObject) json; 
      Class clazz = Class.forName(obj.get("class").getAsString()); 
      return (Movement) clazz.newInstance(); 
     } catch (Exception e) { 
      throw new JsonParseException(e.getMessage()); 
     } 
    } 

} 

Je me suis inscrit désérialiseur:

public void registerAdapters(GsonBuilder gsonBuilder) { 
    gsonBuilder.registerTypeAdapter(Image.class, new ImageDeserialiser()); 
    gsonBuilder.registerTypeAdapter(Button.class, new ButtonDeserialiser()); 
    gsonBuilder.registerTypeAdapter(Animation.class, new AnimationDeserialiser()); 
    gsonBuilder.registerTypeAdapter(Movement.class, new MovementDeserialiser()); 
} 

Alors j'ai essayé de désérialiser la classe qui contient l'interface Mouvement:

playerController = gson.fromJson(new FileReader("data/player_data/player_data.json"), PlayerController.class); 

Mais je reçois cette erreur:

ERROR:Unable to invoke no-args constructor for interface controller.Movement. Register an InstanceCreator with Gson for this type may fix this problem.

Que dois-je besoin faire pour que cela fonctionne? L'idée de spécifier une classe à charger provenait des trucs de configuration de bean de Spring - je ne sais pas s'il y a une meilleure façon de le faire. Oh, et à la lecture de ce que j'ai fait, j'ai déterminé que je ne devrais pas avoir à créer un InstanceCreator pour le Mouvement. Je fournis un désérialiseur personnalisé, après tout ...

Cheers.

Répondre

0

Ah ... j'avais déjà été en train de créer une nouvelle instance Gson où je en avais besoin, mais récemment créé un singleton GsonInstance que je me suis inscrit mon sérialiseurs personnalisés avec. L'objet Gson dont l'objet Movement était désérialisé n'était pas l'objet GsonInstance, donc Gson ne savait pas comment le sérialiser je suppose. Erreur stupide.

tl; dr: Je n'avais pas enregistré le sérialiseur personnalisé avec l'instance Gson particulière que j'utilisais.

0

Vérifiez que controller.TopDownGridMovement a un constructeur sans argument. Si elle ne vous pouvez pas créer une instance de la classe en utilisant:

return (Movement) clazz.newInstance(); 
+0

Oui, oui: public class TopDownGridMovement implémente le mouvement { public TopDownGridMovement() {}} – Mitch

Questions connexes