使用Gson 把字符串转成list
目录
在工作中,需要把字符串转成List<Map>的格式,也便于测试。
语法:
new GsonBuilder().create().fromJson(str,new TypeToken<T>(){}.getType())
代码:
public class GoJsonTest {
public static void main(String[] args) {
goJsonTest();
}
public static void goJsonTest() {
String str = "[{\"form_title\":\"割接审批流程\",\"cur_staff\":[{\"staff_name\":\"feng\",\"org_id\":2015,\"staff_id\":12},{\"staff_name\":\"lang\",\"org_id\":2016,\"staff_id\":4565123},{\"staff_name\":\"yan\",\"org_id\":2017,\"staff_id\":9852314}]}]";
Gson gsonOri = new GsonBuilder().create();
System.out.println("gsonOri: "+gsonOri.fromJson(str,new TypeToken<List<Map<String, Object>>>(){}.getType()));
}
}
结果:
gsonOri: [{form_title=割接审批流程, cur_staff=[{staff_name=feng, org_id=2015.0, staff_id=12.0}, {staff_name=lang, org_id=2016.0, staff_id=4565123.0}, {staff_name=yan, org_id=2017.0, staff_id=9852314.0}]}]
这个结果有个很大的问题,里面的整型数字变成了浮点型的数字,导致在数值匹配中会出现问题。如何处理呢?
ObjectTypeAdapter 实现
看源码,可以看到 ObjectTypeAdapter里面有具体的实现
public final class ObjectTypeAdapter extends TypeAdapter<Object> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == Object.class) {
return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
}
return null;
}
};
private final Gson gson;
private ObjectTypeAdapter(Gson gson) {
this.gson = gson;
}
@Override public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
switch (token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<Object>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap<String, Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
return in.nextDouble();
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
if (typeAdapter instanceof ObjectTypeAdapter) {
out.beginObject();
out.endObject();
return;
}
typeAdapter.write(out, value);
}
}
要修改 read 方面里面对数值型的处理。
case NUMBER:
return in.nextDouble();
重写 ObjectTypeAdapter
public class MapTypeAdapter extends TypeAdapter<Object> {
@Override
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
//判断字符串的实际类型
switch (token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap<>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER: // 处理浮点型的内容
String s = in.nextString();
if (s.contains(".")) {
return Double.valueOf(s);
} else {
try {// 处理整型的数据
return Integer.valueOf(s);
} catch (Exception e) {
return Long.valueOf(s);
}
}
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
@Override
public void write(JsonWriter out, Object value) throws IOException {
// 序列化无需实现
}
}
GsonUtils 重新引用
public class GsonUtils {
private static Gson getGson() {
// 把方面注入到GsonBuilder里面,动态添加
return new GsonBuilder()
.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
}.getType(), new MapTypeAdapter()).create();
}
public static List<Map<String,Object>> changeJsonToList(String str) {
Gson gson = getGson();
return gson.fromJson(str, new TypeToken<List<Map<String, Object>>>() {}.getType());
}
}
测试:
public class GoJsonTest {
public static void main(String[] args) {
gsonTest();
}
public static void gsonTest() {
String str = "[{\"form_title\":\"割接审批流程\",\"cur_staff\":[{\"staff_name\":\"feng\",\"org_id\":2015,\"staff_id\":12},{\"staff_name\":\"lang\",\"org_id\":2016,\"staff_id\":4565123},{\"staff_name\":\"yan\",\"org_id\":2017,\"staff_id\":9852314}]}]";
Gson gsonOri = new GsonBuilder().create();
System.out.println("gsonOri: "+gsonOri.fromJson(str,new TypeToken<List<Map<String, Object>>>(){}.getType()));
System.out.println("gsonChange: "+GsonUtils.changeJsonToList(str));
}
}
结果:
gsonOri: [{form_title=割接审批流程, cur_staff=[{staff_name=feng, org_id=2015.0, staff_id=12.0}, {staff_name=lang, org_id=2016.0, staff_id=4565123.0}, {staff_name=yan, org_id=2017.0, staff_id=9852314.0}]}]
gsonChange: [{form_title=割接审批流程, cur_staff=[{staff_name=feng, org_id=2015, staff_id=12}, {staff_name=lang, org_id=2016, staff_id=4565123}, {staff_name=yan, org_id=2017, staff_id=9852314}]}]
这样就解决了int变成double的问题。
总结:
不必重写整个ObjectTypeAdapter的内容,重写读取的部分,写入部分按原来。有了Gson,对字符串数据的处理就方便很多了便于模拟数据测试用。