问题描述
我有一个对象,需要从JSON中反序列化/解组(使用Gson)。 我的问题是,JavaBean中的属性之一是一个复杂的对象,但需要从数字的JSON数组进行序列化:
JSON是(有点类似于):
{
"name": "John Doe",
"location": [
9.560006,
55.719474
],
}
目标类是(类似于):
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
}
我的GsonBuilder配置为:
new GsonBuilder()
.registerTypeAdapter(Location.class, new LocationTypeConverter())
.create();
我的LocationTypeConverter如下所示:
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);
}
}
但无济于事,因为我一直收到以下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)
需要反序列化的两个类(一个包含Location实例和“包装”对象本身的类)都是简单的JavaBean(具有适当的set'er和get'er方法)。
没有调用序列化,反序列化或读取的方法,所以我在这里做错了什么?
在此先感谢您的帮助!
编辑#1:添加了目标类/ bean,以阐明我要反序列化的对象图。
1楼
这是您需要Ser / des编写的JSON的类:
MyObject {
public String name;
public float[] location;
public float getLatitude() {
if (location != null) return location[0];
return 0;
}
public float getLongitude() {
if (location != null) return location[1];
return 0;
}
}
而您编写的类将具有以下JSON:
{
"name": "John Doe",
"location": {
"longitude": 9.560006,
"latitude": 55.719474
}
}
最后,这是我对您的代码所做的测试,并且工作正常! 也许您只需要确保始终使用相同的Gson对象(从GsonBuilder.create获得的对象)?
Gson gson = new GsonBuilder()
.registerTypeAdapter(Location.class, new LocationTypeConverter())
.setPrettyPrinting()
.create();
UserLocation userLocation = new UserLocation();
userLocation.name = "ciao";
userLocation.location = new Location(1.0, 3.0);
String json = gson.toJson(userLocation);
System.out.println(json);
UserLocation newlocation = gson.fromJson(json, UserLocation.class);
System.out.print(newlocation.location.getLatitude());