도시 정보 데이터를 얻기 위해 Amap의 인터페이스를 사용할 때, 수신되는 json을 java bean으로 변환하기 위해 gson을 사용해야 하며, bean 속성의 데이터 유형은 고유합니다. 그런데 실제로 json을 파싱해보면 데이터가 있는데, 데이터가 있으면 문자열 형태로 전달하고, 데이터가 없으면 [](list type), 데이터가 있으면 [](list)로 전달한다. type) , 데이터가 없으면 [[]] (객체 유형)이 전달됩니다. 일반적으로 구문 분석 중에 예외가 발생합니다.
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)
어댑터를 사용자 정의하고 주석을 달아 json에 전달된 데이터 유형을 Bean으로 캡슐화된 데이터 유형으로 수정할 수 있습니다.
1. 나열할 문자열
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. 객체를 문자열로 변환
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의 모든 속성을 빈으로 캡슐화할 필요는 없습니다.