0

I am using Gson to parse a json string into a Vector which stores 1-2 different sub-classes of BackgroundShape.
Example, BGRectangle and BGTriangle.
When I try to parse the string I get this error ..

FileReader in = new FileReader("levels/level1.json");
BufferedReader br = new BufferedReader(in);
LevelDefinition ld = new Gson().fromJson(br, LevelDefinition.class);

Caused by: java.lang.StackOverflowError
    at com.google.gson.internal.$Gson$Types.resolve

Is there a better way to achieve this?
I'm trying to place sub classes into a Vector of their parents type. This is the parent class ..

public abstract class Shape{

    protected int textureIndex;

    /**
     * @param textureIndex
     */
    public Shape(int textureIndex) {
        this.textureIndex = textureIndex;
    }

    protected abstract void draw(GLAutoDrawable gLDrawable);
}

BackgroundShape subclasses Shape ..

public abstract class BackgroundShape extends Shape{

    private Vec3 position;

    public BackgroundShape(Vec3 position, int textureIndex) {
        super(textureIndex);

        this.position = position;
    }
}

BGRectangle extends BackgroundShape ..

public class BGRectangle extends BackgroundShape{

    private float width;
    private float height;

    public BGRectangle (Vec3 position int textureIndex, float width, float height) { 
        super(position, textureIndex);

        this.width = width;
        this.height = height;
    };

    @Override
    public void draw(GLAutoDrawable gLDrawable) {
    }
}

This is how I declare in json (only 1 BackgroundShape for demo) ..

{
    "bgShapes": [
        {
            "position": {
                "x": 0.0,
                "y": 50.0,
                "z": -20.0
            },
                    "textureSelection": 1,
            "width": 450.0,
            "height": 200.0
        }
    ]
}

And my Java class representing this json string ..

public class LevelDefinition {

    private Vector<BackgroundShape> bgShapes;

    /**
     * @return the bgShapes
     */
    public Vector<BackgroundShape> getBgShapes() {
        return bgShapes;
    }
    /**
     * @param bgShapes the bgShapes to set
     */
    public void setBgShapes(Vector<BackgroundShape> bgShapes) {
        this.bgShapes = bgShapes;
    }
}
bobbyrne01
  • 6,295
  • 19
  • 80
  • 150
  • I don't see any info there that will tell Gson that it needs to create BGRectangles. I'm guessing it gets lost looking for somewhere to put width and height. – Hot Licks May 20 '14 at 00:30

1 Answers1

0

It looks like this bug to me.

The way I worked around it is to write my own JsonReader and JsonWriter. You can read more about how to do this in my answer here: How do I implement TypeAdapterFactory in Gson?

Basically, implement the read method in TypeAdapter to create the Vector class you want. If this is not enough for you to figure it out let me know and I will try to add more detail.

You can start with something like this:

public enum ShapeTypeAdapterFactory implements TypeAdapterFactory {
    INSTANCE;

    private static class ShapeTypeAdapter extends TypeAdapter<BackgroundShape> {
        @Override
        public final void write(JsonWriter out, BackgroundShape value) throws IOException {
            if(value == null) {
                out.nullValue();
                return;
            }

            // Your code goes here
        }

        @Override
        public final BackgroundShape read(JsonReader in) throws IOException {
            if(in.peek() == JsonToken.NULL) {
                in.nextNull();
                return null;
            }

            // Your code goes here      

            // Don't return null, return the new object
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if(!BackgroundShape.class.isAssignableFrom(type.getRawType())) {
            return null;
        }

        return (TypeAdapter<T>) new ShapeTypeAdapter();
    }
}

Then register it with:

gsonBuilder.registerTypeAdapterFactory(ShapeTypeAdapterFactory.INSTANCE);

Also, read this Javadoc for a more complete example about how to write the code missing from this sample

Community
  • 1
  • 1
durron597
  • 31,968
  • 17
  • 99
  • 158
  • Hm, the link you provided mentions creating `TypeAdapterFactory` to handle the multiple possible sub-classes of `BackgroundShape` .. Could you help there please? – bobbyrne01 May 21 '14 at 20:33