I've got an object, which I need deserialized / unmarshalled from JSON (using Gson). My problem is that one of the properties, in my JavaBean, is a complex object, but needs to be serialized fron a JSON array of numbers:
The JSON is (somewhat similar to):
{
"name": "John Doe",
"location": [
9.560006,
55.719474
],
}
The targeted classes are (somwaht similar to):
class UserLocation {
private String name;
private Location location;
// ... "zero-args constructor", get'ers and set'ers
}
class Location {
private double longitude;
private double latitude;
// ... "zero-args constructor", get'ers and set'ers
}
My GsonBuilder is configured as:
new GsonBuilder()
.registerTypeAdapter(Location.class, new LocationTypeConverter())
.create();
Where my LocationTypeConverter looks like this:
public class LocationTypeConverter extends TypeAdapter<Location> implements JsonSerializer<Location>, JsonDeserializer<Location> {
private static final int LONGITUDE_INDEX = 0;
private static final int LATITUDE_INDEX = 1;
@Override
public JsonElement serialize(Location src, Type srcType, JsonSerializationContext context) {
JsonArray array = new JsonArray();
array.set(LATITUDE_INDEX, new JsonPrimitive(src.getLatitude()));
array.set(LONGITUDE_INDEX, new JsonPrimitive(src.getLongitude()));
return array;
}
@Override
public Location deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonArray array = json.getAsJsonArray();
return new Location(array.get(LATITUDE_INDEX).getAsDouble(), array.get(LONGITUDE_INDEX).getAsDouble());
}
@Override
public void write(JsonWriter out, Location value) throws IOException {
out.beginArray().value(value.getLongitude()).value(value.getLatitude()).endArray();
}
@Override
public Location read(JsonReader in) throws IOException {
in.beginArray();
double longitude = in.nextDouble();
double latitude = in.nextDouble();
in.endArray();
return new Location(longitude, latitude);
}
}
But to no avail, since I keep recieving the following Stacktrace:
retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 85 path $[0].location
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:377)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
Caused by: retrofit.converter.ConversionException: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 85 path $[0].location
at retrofit.converter.GsonConverter.fromBody(GsonConverter.java:67)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:362)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 85 path $[0].location
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:103)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson.fromJson(Gson.java:810)
at com.google.gson.Gson.fromJson(Gson.java:775)
at retrofit.converter.GsonConverter.fromBody(GsonConverter.java:63)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:362)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 85 path $[0].location
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:189)
The two classes that needs to be deserialized (the one containing the Location instance and the "wrapping" object itself are both simple JavaBean (with appropriate set'er and get'er methods.
None of the methods serialize, deserialize nor read are being called, so what am I doing wrong here?
Thanks in advance, for your help!
EDIT #1: Added target classses / beans to clarify the object graph I'm trying to deserialize to.