13

I have the following POJOs:

public interface Shape {
    public double calcArea();
    public double calcPerimeter();
}

public class Rectangle implement Shape {
    // Various properties of a rectangle
}

public class Circle implements Shape {
    // Various properties of a circle
}

public class ShapeHolder {
    private List<Shape> shapes;

    // other stuff
}

I have no problem getting GSON to serialize an instance of ShapeHolder to JSON. But when I try to deserialize a String of that JSON back into a ShapeHolder instance, I get errors:

String shapeHolderAsStr = getString();
ShapeHolder holder = gson.fromJson(shapeHodlderAsStr, ShapeHolder.class);

Throws:

Exception in thread "main" java.lang.RuntimeException: Unable to invoke no-args constructor for interface    
net.myapp.Shape. Register an InstanceCreator with Gson for this type may fix this problem.
    at com.google.gson.internal.ConstructorConstructor$8.construct(ConstructorConstructor.java:167)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:162)
    ... rest of stack trace ommitted for brevity

So I looked here and started implementing my own ShapeInstanceCreator:

public class ShapeInstanceCreator implements InstanceCreator<Shape> {
    @Override
    public Shape createInstance(Type type) {
        // TODO: ???
        return null;
    }
}

But now I'm stuck: I'm only given a java.lang.reflect.Type, but I really need a java.lang.Object so I can write code like:

public class ShapeInstanceCreator implements InstanceCreator<Shape> {
    @Override
    public Shape createInstance(Type type) {
        Object obj = convertTypeToObject(type);

        if(obj instanceof Rectangle) {
            Rectangle r = (Rectangle)obj;
            return r;
        } else {
            Circle c = (Circle)obj;
            return c;
        }

        return null;
    }
}

What can I do?

Update

Per @raffian's suggestion (the link he/she posted), I implemented an InterfaceAdapter exactly like the one in the link (I didn't change anything). Now I'm getting the following exception:

Exception in thread "main" com.google.gson.JsonParseException: no 'type' member found in what was expected to be an interface wrapper
    at net.myapp.InterfaceAdapter.get(InterfaceAdapter.java:39)
    at net.myapp.InterfaceAdapter.deserialize(InterfaceAdapter.java:23)

Any ideas?

halfer
  • 19,824
  • 17
  • 99
  • 186
IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • Check this: http://stackoverflow.com/a/19600090/1360888, it has a base class instead of a interface but it's like your problem. – giampaolo Dec 08 '13 at 10:26

2 Answers2

10

Did you look at this? Looks like a nice clean way to implement InstanceCreators.

I was using Gson too, but switched to FlexJSON due to serialization issues. With Flex, you don't need instance creators, just make sure your objects have getters/setters for all fields based on JavaBean spec, and you're good to go:

 ShapeHolder sh = new ShapeHolder();
 sh.addShape(new Rectangle());
 sh.addShape(new Circle());
 JSONSerializer ser = new JSONSerializer();
 String json = ser.deepSerialize(sh);
 JSONDeserializer<ShapeHolder> der = new JSONDeserializer<ShapeHolder>();
 ShapeHolder sh2 = der.deserialize(json);
Community
  • 1
  • 1
raffian
  • 31,267
  • 26
  • 103
  • 174
  • Thanks @raffian (+1) - I created an `InterfaceAdapter` like the example shows in the link you posted. I then registered it as a type adaptor with the `GsonBuilder` (again like the example shows). Now I'm getting a new error (please see my updated question). Any ideas as to what's going on now? Thanks again! – IAmYourFaja Dec 08 '13 at 00:20
  • I don't, apologies, this is why I switched to flex, to avoid all this crap! :-) Is there any constraint forcing you to use Gson? – raffian Dec 08 '13 at 00:25
  • Sorry for the delayed response - I went to bed and just gave FlexJSON a whirl. What a treat! Imagine that: serialization/deserialization that "just works" right out of the box! You've definitely converted me - thanks! – IAmYourFaja Dec 08 '13 at 16:20
  • exactly, it just works, welcome to the dark side :-) – raffian Dec 08 '13 at 16:33
1

NOTE that FlexJSON is adding class name as part of json like below serialize time.

{
    "HTTPStatus": "OK",
    "class": "com.XXX.YYY.HTTPViewResponse",
    "code": null,
    "outputContext": {
        "class": "com.XXX.YYY.ZZZ.OutputSuccessContext",
        "eligible": true
    }
}

So JSON will be cumber some; but you don't need write InstanceCreator which is required in GSON.

Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101