Gson 如何避免 Expected BEGIN_ARRAY but was BEGIN_OBJECT?
Gson how to avoid Expected BEGIN_ARRAY but was BEGIN_OBJECT?
我正在使用 GSON 将 JSON 数据解析为 Java,我 运行 进入了标题中所述的错误。我正在使用 API returns 以下 JSON 数据 :
{
"STATUS": "SUCCESS",
"NUM_RECORDS": "5",
"MESSAGE": "5 records found",
"AVAILABILITY_UPDATED_TIMESTAMP": "2015-05-03T13:59:08.541-07:00",
"AVAILABILITY_REQUEST_TIMESTAMP": "2015-05-03T13:59:08.490-07:00",
"AVL": [
{
"TYPE": "ON",
"BFID": "205052",
"NAME": "5th St (500-598)",
"RATES": {
"RS": [
{
"BEG": "12:00 AM",
"END": "12:00 PM",
"RATE": "0",
"RQ": "No charge"
},
{
"BEG": "12:00 PM",
"END": "6:00 PM",
"RATE": "5",
"RQ": "Per hour"
},
{
"BEG": "6:00 PM",
"END": "12:00 AM",
"RATE": "0",
"RQ": "No charge"
}
]
},
"PTS": "2",
"LOC": "-122.4002212834,37.7776161738,-122.3989619795,37.7766113458"
},
{
"TYPE": "ON",
"BFID": "205042",
"NAME": "5th St (450-498)",
"RATES": {
"RS": {
"BEG": "12:00 AM",
"END": "12:00 AM",
"RATE": "0",
"RQ": "No charge"
}
},
"PTS": "2",
"LOC": "-122.4015027158,37.7786330718,-122.4005149869,37.7778485214"
},
]
}
我可以看出问题出在哪里,RS
字段可以包含一个 object 的数组(我们称之为 object RInfo
)或一些在某些情况下,它将仅包含数组中未包含的 RInfo
object 之一。我认为错误的发生是因为 GSON 正在寻找一个数组但发现了一个 object。我无法更改 JSON 文件的结构,因为它是由 API 提供的。
只要 RS
是 RInfo
object 的数组,我就能成功解析信息,但在某些情况下 RS
只包含一个 RInfo
object 所以出现这个错误。
有没有办法在 GSON 中处理这个问题?
*更新
我已经尝试过之前链接的解决方案。这是我从该解决方案中获得的信息:
class RSDeserializer implements JsonDeserializer<RateInfo[]> {
@Override
public RateInfo[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
if (json instanceof JsonArray) {
System.out.println("fromJson in RSD:" + new Gson().fromJson(json, RateInfo[].class));
return new Gson().fromJson(json, RateInfo[].class);
}
RateInfo rI = context.deserialize(json, RateInfo.class);
return new RateInfo[] { rI };
}
}
我也新建了一个GsonBuilder如下
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(RateInfo[].class, new RSDeserializer());
Gson gson = gsonBuilder.create();
似乎从未使用过自定义反序列化器,因为打印语句从未在控制台中打印出来。之后,我尝试使用 MyOBJ info = gson.fromJson(json, MyOBJ.class);
对 json 进行反序列化,此行给出了 Expected BEGIN_ARRAY but was BEGIN_OBJECT exception.
您必须更新反序列化器以表明您想要 return a List<RateInfo>
:
class RSDeserializer implements JsonDeserializer<List<RateInfo>> {
@Override
public List<RateInfo> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json instanceof JsonArray) {
return Arrays.asList(context.deserialize(json, RateInfo[].class));
}
return Collections.singletonList(context.deserialize(json, RateInfo.class));
}
}
并且您还需要告诉解析器这也是您在注册此适配器时要反序列化的类型:
Type t = new TypeToken<List<RateInfo>>(){}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(t, new RSDeserializer()).create();
可以在我的 gist.
中找到完整的工作示例
我正在使用 GSON 将 JSON 数据解析为 Java,我 运行 进入了标题中所述的错误。我正在使用 API returns 以下 JSON 数据 :
{
"STATUS": "SUCCESS",
"NUM_RECORDS": "5",
"MESSAGE": "5 records found",
"AVAILABILITY_UPDATED_TIMESTAMP": "2015-05-03T13:59:08.541-07:00",
"AVAILABILITY_REQUEST_TIMESTAMP": "2015-05-03T13:59:08.490-07:00",
"AVL": [
{
"TYPE": "ON",
"BFID": "205052",
"NAME": "5th St (500-598)",
"RATES": {
"RS": [
{
"BEG": "12:00 AM",
"END": "12:00 PM",
"RATE": "0",
"RQ": "No charge"
},
{
"BEG": "12:00 PM",
"END": "6:00 PM",
"RATE": "5",
"RQ": "Per hour"
},
{
"BEG": "6:00 PM",
"END": "12:00 AM",
"RATE": "0",
"RQ": "No charge"
}
]
},
"PTS": "2",
"LOC": "-122.4002212834,37.7776161738,-122.3989619795,37.7766113458"
},
{
"TYPE": "ON",
"BFID": "205042",
"NAME": "5th St (450-498)",
"RATES": {
"RS": {
"BEG": "12:00 AM",
"END": "12:00 AM",
"RATE": "0",
"RQ": "No charge"
}
},
"PTS": "2",
"LOC": "-122.4015027158,37.7786330718,-122.4005149869,37.7778485214"
},
]
}
我可以看出问题出在哪里,RS
字段可以包含一个 object 的数组(我们称之为 object RInfo
)或一些在某些情况下,它将仅包含数组中未包含的 RInfo
object 之一。我认为错误的发生是因为 GSON 正在寻找一个数组但发现了一个 object。我无法更改 JSON 文件的结构,因为它是由 API 提供的。
只要 RS
是 RInfo
object 的数组,我就能成功解析信息,但在某些情况下 RS
只包含一个 RInfo
object 所以出现这个错误。
有没有办法在 GSON 中处理这个问题?
*更新
我已经尝试过之前链接的解决方案。这是我从该解决方案中获得的信息:
class RSDeserializer implements JsonDeserializer<RateInfo[]> {
@Override
public RateInfo[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
if (json instanceof JsonArray) {
System.out.println("fromJson in RSD:" + new Gson().fromJson(json, RateInfo[].class));
return new Gson().fromJson(json, RateInfo[].class);
}
RateInfo rI = context.deserialize(json, RateInfo.class);
return new RateInfo[] { rI };
}
}
我也新建了一个GsonBuilder如下
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(RateInfo[].class, new RSDeserializer());
Gson gson = gsonBuilder.create();
似乎从未使用过自定义反序列化器,因为打印语句从未在控制台中打印出来。之后,我尝试使用 MyOBJ info = gson.fromJson(json, MyOBJ.class);
对 json 进行反序列化,此行给出了 Expected BEGIN_ARRAY but was BEGIN_OBJECT exception.
您必须更新反序列化器以表明您想要 return a List<RateInfo>
:
class RSDeserializer implements JsonDeserializer<List<RateInfo>> {
@Override
public List<RateInfo> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json instanceof JsonArray) {
return Arrays.asList(context.deserialize(json, RateInfo[].class));
}
return Collections.singletonList(context.deserialize(json, RateInfo.class));
}
}
并且您还需要告诉解析器这也是您在注册此适配器时要反序列化的类型:
Type t = new TypeToken<List<RateInfo>>(){}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(t, new RSDeserializer()).create();
可以在我的 gist.
中找到完整的工作示例