List of Abstract Classes, _class to determine type

289 views
Skip to first unread message

shaunpatterson

unread,
Jul 18, 2012, 11:02:11 AM7/18/12
to google-gson
I have a case where I'm pulling a list of abstract objects out of
mongodb with Spring-Data. With Spring, if you store a list of
abstracts -- like List<Shape> it'll put:

_class : "com.shape.Circle"

in the database so that Spring-Data knows what kind of shape to create
when pulling. I'm looking to replicate this with Gson is a generic
fashion... if possible.

I got close but... but not quite:

public abstract class AbstractSpringObject {
@SerializedName("_class")
public String clazz;
}

public class AbstractSpringObjectAdapter implements
JsonDeserializer<AbstractSpringObject> {
@Override
public AbstractSpringObject deserialize(JsonElement json, Type
typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
try {
JsonObject jsonObject = json.getAsJsonObject();
return context.deserialize(json,
Class.forName((String)jsonObject.get("_class").getAsString()));
} catch (ClassNotFoundException cnfe) {
LOGGER.fatal("Error processing Abstract Spring Object");
throw new JsonParseException("Invalid Abstract Spring Object",
cnfe);
}

}
}

Then I registered AbstractSpringObject as a type adapter in the Gson
builder. Now... this seems to work for List<AbstractSpringObject> but
not for List<Shape> (assuming shape extends AbstractSpringObject). I
tried registering as a hierarchical type adapter... but that gave me
an infinite loop in the adapter.

Any other ideas?

Thanks

--
Shaun


Jesse Wilson

unread,
Jul 18, 2012, 11:25:26 PM7/18/12
to googl...@googlegroups.com
Take a look at RuntimeTypeAdapterFactory.

There are some example usages in the test case for that class:

Note that this class isn't a part of core Gson; you'll need to copy the RuntimeTypeAdapterFactory.java file into your project if you want to use it.

shaunpatterson

unread,
Jul 19, 2012, 8:46:23 AM7/19/12
to google-gson
Jesse,

I've actually looked into this solution. I don't think this'll work
for me. You have to register your subclasses. That could be a lot of
subclasses for me in the future. Secondly, my Gson object is actually
created in a Jersey Provider class in a "utilities" jar that wouldn't
have access to all the subtypes I would want to transform

--
Shaun

Brandon Mintern

unread,
Jul 19, 2012, 8:22:43 PM7/19/12
to googl...@googlegroups.com
Hi Shaun,

You might want to check out my github project:
https://github.com/BMintern/gson-interface

Using that pattern, you would be able to do something like this:

public class ShapeDeserializer implements JsonDeserializes<Shape> {
@Override
public Shape fromJsonTree(JsonElement json, Type type,
GsonContext<Shape> context) {
JsonObject jsonObject = json.getAsJsonObject();
Class<? extends Shape> clazz = (Class<? extends Shape>)
Class.forName(jsonObject.get("_class").getAsString());
return context.thisFromJsonTree(json, clazz);
}
}

public class Shape implements JsonDeserialization<ShapeDeserializer> { ... }


Does that help at all?

shaunpatterson

unread,
Jul 20, 2012, 9:00:07 AM7/20/12
to google-gson
Brandon,

Very interesting. I can see quite a few use cases for this
interface. Any plans to merge it into the gson release?

--
Shaun

Brandon Mintern

unread,
Jul 23, 2012, 4:08:54 PM7/23/12
to googl...@googlegroups.com
Hi Shaun,

Thanks for your kind remarks! I do plan to submit a patch after I add
more functionality to expand the use cases it supports.

For example, I am currently adding interfaces to allow default object
instances to deserialize *themselves* from either a JsonElement or a
JsonReader. In conjunction with this, it becomes helpful to have a
TypeSelector<Foo> (or TypeDispatcher) that determines what Class<?
extends Foo> should be created based on the contents of a
JsonReader/JsonElement (this would be helpful in your example, I
believe).

This is not the entirety of what I'm working on; there is a lot of
functionality that makes sense when you start going down this path. I
expect to have something in a few weeks that should be quite
interesting to Gson developers and users.

Thanks again,
Brandon
> --
> You received this message because you are subscribed to the Google Groups "google-gson" group.
> To post to this group, send email to googl...@googlegroups.com.
> To unsubscribe from this group, send email to google-gson...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/google-gson?hl=en.

Inderjeet Singh

unread,
Jul 25, 2012, 2:00:05 PM7/25/12
to googl...@googlegroups.com
Hi Brandon, 

It would be great if you can create a TypeAdapter version of your library instead of the one that uses JsonSerializer/JsonDeserializer.
The performance of TypeAdapters is much better since with them you do reflection just once. JsonSerializer/JsonDeserializer are not deprecated but should be used only when absolutely necessary.

Thanks
Inder

> To unsubscribe from this group, send email to google-gson+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages