Removing interface deserialization in GSON

I could not think of a better way to formulate this question, but basically I want to save the name of a particular class in GSON (see "movement"):

{ "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" } } 

This is the class that contains the Movement interface that I want to use for deserialization:

 public class PlayerController { private Player player; private DelayTimer movementDelay; private Movement movement; public PlayerController() { } [...] } 

I wrote my own deserializer:

 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()); } } } 

I registered a deserializer:

 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()); } 

Then I tried to deserialize the class containing the Movement interface:

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

But I get this error:

ERROR: Unable to invoke the no-args constructor for the interface controller. Traffic. Registering InstanceCreator with Gson for this type can solve this problem.

What do I need to do to make this work? The idea of ​​specifying the class to load came from the Spring bean config stuff - not sure if there is a better way to do this.

Oh, and from the reading I did, I decided that I did not need to create an InstanceCreator for Movement. In the end, I provide a custom deserializer ...

Greetings.

+6
source share
2 answers

Ah ... I previously created a new instance of Gson, wherever I needed it, but I recently created a singleton GsonInstance, with which I registered my own serializers. The Gson object in which the Movement object was deserialized was not a GsonInstance object, so Gson did not know how to serialize it, I think. Stupid mistake.

tl; dr: I have not registered my own serializer with the specific Gson instance that I used.

0
source

Verify controller.TopDownGridMovement has a no-arg constructor. If this is not the case, you cannot create an instance of the class using:

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

Source: https://habr.com/ru/post/899839/


All Articles