[英]Gson parsing “null” objects as Array/Object?
我从服务器得到的回报可以是:
[{
"id":"1",
"objectOne": {
"name":"jim"
}
}, {
"id":"1",
"objectOne": [{
"name": "jim1"
}, {
"name": "jim2"
}
}, {
"id":"1",
"objectOne": null
}]
也就是说,一个值可以是一个对象,一个对象数组或null。
我正在将Gson转换器与Retrofit一起使用,并且正在使用此TypeAdapterFactory强制将单个对象读取为数组:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(new ObjectToArrayFactory());
Gson gson = gsonBuilder.create();
厂:
private class ObjectToArrayAdapter<T> extends TypeAdapter<List<T>> {
Gson gson;
private Class<T> adapterclass;
public ObjectToArrayAdapter(Gson gson, Class<T> adapterclass) {
this.gson = gson;
this.adapterclass = adapterclass;
}
@Override
public void write(JsonWriter out, List<T> value) throws IOException {}
public List<T> read(JsonReader reader) throws IOException {
List<T> list = new ArrayList<T>();
if (reader.peek() == JsonToken.BEGIN_OBJECT) {
// If it's meant to be an array and instead it's a single object, add it to a newly created list.
parseObject(list, reader, gson);
} else if (reader.peek() == JsonToken.BEGIN_ARRAY) {
// Otherwise, if it is actually a list, manually parse each item and add it to the list
parseArray(list, reader, gson);
} else if(reader.peek() == JsonToken.NULL) {
// However if the server gives a null object, just return null.
return null;
}
return list;
}
private void parseArray(List<T> list, JsonReader reader, Gson gson) throws IOException {
reader.beginArray();
while (reader.hasNext()) {
parseObject(list, reader, gson);
}
reader.endArray();
}
private void parseObject(List<T> list, JsonReader reader, Gson gson) throws IOException {
T inning = gson.fromJson(reader, adapterclass);
list.add(inning);
}
}
我的问题是,当我要求Retrofit将值解析为Array时:
private List<PaymentsOption> objectOne;
当进入json的部分时,Gson解析器似乎会感到困惑:
"objectOne": null
我已经调试并记录了解析过程,似乎遵循了此代码路径的含义(为简便起见,我已经解析了实际的代码):
if(reader.peek() == JsonToken.BEGIN_ARRAY) {
reader.beginArray();
while(reader.hasNext()) { // public void parseTag()
if(reader.peek() == JsonToken.BEGIN_OBJECT) {
T inning = gson.fromJson(reader, adapterclass); <-- Crashes here
}
}
reader.endArray();
}
因此,不应将它作为“ null”作为beginArray“偷看”。 它还不应该允许reader.beginArray(),因为它仍然是“ null”。 它应该再次窥视并看到beginObject。 它可以让内部的reader.beginObject() gson.fromJson
但未能上reader.readName(),因为它实际上是读“空”。 异常如下:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a name but was NULL at line 24 column 39 path $[1].objectOne
10-27 12:05:20.452 E/Exception: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
10-27 12:05:20.452 E/Exception: at com.google.gson.Gson.fromJson(Gson.java:810)
10-27 12:05:20.452 E/Exception: at uk.co.utils.network.ObjectToArrayFactory$ObjectToArrayAdapter.parseTag(ObjectToArrayFactory.java:70)
我不明白为什么reader.peek()首先显示一个beginArray,允许reader.beginArray(),然后将reader.peek()显示为beginObject(),以及为什么它允许reader.beginObject()。 据我了解,它应该显示一个reader.peek()== Json.Token.NULL ...?
构建gson对象时,需要编写TypeAdapter
并进行注册。 在适配器的read方法中,您可以检查给定的参数是否为null或为空,或者为空,然后采取相应的措施。您的read方法将如下所示:
public Number read(JsonReader in) throws IOException{
if(in.peek() == JsonToken.NULL) in.nextNull();
try{
//read value and take suitable action
}catch(Exception e){}
}
但是您需要为每种需要特殊处理的不同数据类型编写一个typeAdapter。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.