在使用高德的接口去获取城市信息的数据时,需要使用gson将传入的json转换成java bean,bean的属性的数据类型是唯一的。但是实际在解析json的时候,有的数据:有数据时是传入的是string类型,没有数据的时候,传入的是[](list类型);或者是有数据是[](list类型),没有数据的时候,传入的是[[]](object类型)。通常在解析的时候,会抛出异常。
09-26 18:29:58.735 2834 4082 W System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 225 path $.data.city.addressComponent.streetNumber.number
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
09-26 18:29:58.735 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
09-26 18:29:58.736 2834 4082 W System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
09-26 18:29:58.736 2834 4082 W System.err: at com.google.gson.Gson.fromJson(Gson.java:932)
09-26 18:29:58.736 2834 4082 W System.err: at com.google.gson.Gson.fromJson(Gson.java:897)
09-26 18:29:58.736 2834 4082 W System.err: at com.google.gson.Gson.fromJson(Gson.java:846)
09-26 18:29:58.736 2834 4082 W System.err: at com.google.gson.Gson.fromJson(Gson.java:817)
可以通过自定义adapter结合注解的方式,将json传入的数据类型修改成bean封装的数据类型。
1、String转List
public class CityAdapter extends TypeAdapter<List<String>> {
@Override
public void write(JsonWriter out, List<String> value) throws IOException {
}
@Override
public List<String> read(JsonReader in) throws IOException {
List<String> cityList = new ArrayList<>();
JsonToken token = in.peek();
if (token == JsonToken.STRING) {
String value = in.nextString();
cityList.add(value);
} else if (token == JsonToken.BEGIN_ARRAY) {
in.beginArray();
while (in.hasNext()) {
String value = in.nextString();
cityList.add(value);
}
in.endArray();
}
return cityList;
}
}
2、object转String
public class BusinessAreaAdapter extends TypeAdapter<List<CityData.BusinessArea>> {
@Override
public void write(JsonWriter out, List<CityData.BusinessArea> value) throws IOException {
}
@Override
public List<CityData.BusinessArea> read(JsonReader in) throws IOException {
List<CityData.BusinessArea> businessAreas = new ArrayList<>();
JsonToken token = in.peek();
if (token == JsonToken.BEGIN_ARRAY) {
in.beginArray();
while (in.hasNext()) {
JsonToken innerToken = in.peek();
if (innerToken == JsonToken.BEGIN_OBJECT) {
CityData.BusinessArea businessArea = readBusinessArea(in);
businessAreas.add(businessArea);
} else if (innerToken == JsonToken.BEGIN_ARRAY) {
in.skipValue();
}
}
in.endArray();
}
return businessAreas;
}
private CityData.BusinessArea readBusinessArea(JsonReader in) throws IOException {
CityData.BusinessArea businessArea = new CityData.BusinessArea();
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
if (name.equals("name")) {
businessArea.setName(in.nextString());
} else if (name.equals("location")) {
businessArea.setLocation(in.nextString());
} else if (name.equals("id")) {
businessArea.setId(in.nextString());
}
}
in.endObject();
return businessArea;
}
}
在java bean中通过注解的方式来进行转换
public class AddressComponent {
private String province;
//哪个属性需要转换,就在哪个属性上加注解
@JsonAdapter(CityAdapter.class)
private List<String> city;
private String district;
// 构造器
// getter && setter
// ...
}
以下是json转java bean的一些注意事项:
① bean中属性名必须和json中的一致,bean的类型可以不一致,否则转义失败
② 转义需要的属性即可,不需要将json中所有的属性都封装到bean中