Gson Adapter的用法
使用了Gson库,别的不好说,感觉Adapter的设计模式和要处理的任务太贴合了,Gson提供了TypeAdapter接口,正好写一下处理的过程。
我遇到的情况相对还算比较麻烦,处理高德地图返回的Json,主要有三个问题
- 递归定义问题。districts里边有一个数组,里边是很多districts.
{
"notcare1": "notcare1",
"notcare2": "notcare2",
"districts":[{
"citycode": [],
"adcode" : "adcode",
"name" : "name",
"notcare3": "notcare3",
"districts":[
"citycode": "citycode",
"adcode" : "adcode",
"name" : "name",
"b" : "b"
]
},{
"a": "a",
"b" : "b",
"districts":[
]
}
]
}
抽象写成Java类是这样的
public class Districts {
String citycode;
String adcode;
String name;
List<Districts> districtsList;
}
-
嵌套定义问题外层如上文所示,外层并不是一个distict,定义成Java类是这样的
public class DistrictsFromAmap { List<Districts> districtsList; }
-
类型不确定问题。
citycode可能是个空数组,也可能是个字符串。好在我们希望处理后都是字符串
上文已经给出了针对上述问题实体怎么定义。Adapter怎么写?
首先处理递归问题。思想是,递归调用write(),read()。write直接遍历数组,read要创建数组再创建对象。
然后解决类型不确定问题。因为我就要String,只需要再in中处理即可。注意beginArray()和endArray()的配对问题。
package cn.aaronhu.cabinbackend.entity.districts;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.ArrayList;
public class DistrictTypeAdapter extends TypeAdapter<Districts> {
private final Gson gson;
public DistrictTypeAdapter() {
this.gson = new Gson();
}
@Override
public void write(JsonWriter out, Districts districts) throws IOException {
out.beginObject();
out.name("citycode").value(districts.citycode);
out.name("adcode").value(districts.adcode);
out.name("name").value(districts.name);
out.name("districts").beginArray();
for (Districts childDistricts : districts.districtsList) {
write(out,childDistricts);
}
out.endArray();
out.endObject();
}
@Override
public Districts read(JsonReader in) throws IOException {
Districts districts = new Districts();
in.beginObject();
while(in.hasNext()){
switch (in.nextName()){
case "citycode":
switch (in.peek()){
case STRING:
districts.citycode = in.nextString();
break;
case BEGIN_ARRAY:
districts.citycode = gson.fromJson(in,Object.class).toString();
break;
default:
throw new IllegalStateException("Unexpected" + in.peek());
}
break;
case "adcode":
districts.adcode = in.nextString();
break;
case "name":
districts.name = in.nextString();
break;
case "districts":
districts.districtsList = new ArrayList<>();
in.beginArray();
while(in.hasNext()){
districts.districtsList.add(read(in));
}
in.endArray();
break;
default:
in.skipValue();
break;
}
}
in.endObject();
return districts;
}
}
接下来解决嵌套定义问题
package cn.aaronhu.cabinbackend.entity.districts;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.util.ArrayList;
public class DistrictsFromAmapAdapter extends TypeAdapter<DistrictsFromAmap> {
@Override
public void write(JsonWriter out, DistrictsFromAmap districtsFromAmap) throws IOException {
out.beginObject();
out.name("districtList");
out.beginArray();
for(Districts districts: districtsFromAmap.getDistrictsList()) {
new DistrictTypeAdapter().write(out,districts);
}
out.endArray();
out.endObject();
}
@Override
public DistrictsFromAmap read(JsonReader in) throws IOException {
DistrictsFromAmap districtsFromAmap = new DistrictsFromAmap();
in.beginObject();
while (in.hasNext()){
if ("districts".equals(in.nextName())) {
districtsFromAmap.districtsList = new ArrayList<>();
in.beginArray();
while(in.hasNext()){
districtsFromAmap.districtsList.add(new DistrictTypeAdapter().read(in));
}
in.endArray();
} else {
in.skipValue();
}
}
in.endObject();
return districtsFromAmap;
}
}
比较难受的是上来就是一个数组
常见错误分析:
JsonReader in 一个一个字段读,比如
{
"a" : "b",
"c" : "d"
}
比如我想读"a"后读"c",然后获取"d",要调用
[in.nextName(),in.skipValue(),in.nextName(),in.nextString()]