您的代码存在多个问题:
- 结果列表类型是原始的,因此在编译时它不是类型安全的。
- 如果可能,首选接口
List,而不是类ArrayList。
-
T 的类型参数未绑定到它返回的列表,因此如果有的话几乎没有意义。
- 从 type 参数创建类型标记的方式不起作用:在运行时它仍然映射到
java.lang.Object 并且 Gson 试图选择
它认为最好的一个。
- 不应(而且不能)在此类方法中创建类型标记,而是从调用站点传递。此外,它们是不可变的,因此也是线程安全的。
- 您无需在每次调用此方法时都创建
Gson 实例。
- 在这种情况下将 JSON 树转换为字符串是非常没用的,因为 Gson 可以遍历 JSON 树并读取 JSON 令牌流,而无需花费双倍的时间
解析。
当我要求你提供列表元素类时,我试图暗示你的实际代码是这样的:
ArrayList arrayList = toArrayList(jsonArray);
System.out.println(arrayList);
无法工作。请注意以下几点:
- 此代码(也可能是您的代码)根本没有提及元素类型。
- 如果您检查 real 列表元素类,您会看到它被反序列化为
com.google.gson.internal.LinkedTreeMap--来自 Gson 的泛型类型
我在上面谈论的观点 (arrayList.get(0).getClass())。
- JSON 不区分“long”、“integer”、“short”、“u64”、“i8”等。 JSON 数字类型只是一个数字。格森
选择
java.lang.Double,因为这种类型可以满足大多数实际需求(BigDecimal 会是一个更好的选择,但它也很消耗内存;这也是
为什么setLongSerializationPolicy 提示被忽略)。
Gson 尽其所能为您做到了。
总结一下,你要做的是:
private static final Gson gson=new GsonBuilder()
.disableInnerClassSerialization()
.disableHtmlEscaping()
.create();
public static<E> List<E> toArrayList(final JsonArray jsonArray,final TypeToken<?extends List<? extends E>> typeToken){
return gson.fromJson(jsonArray,typeToken.getType());
}
final class MyObject {
@Expose
@SerializedName("serialNo")
final String serialNo;
@Expose
@SerializedName("createBy")
final String createBy;
@Expose
@SerializedName("createDate")
final long createDate;
@Expose
@SerializedName("updateBy")
final String updateBy;
@Expose
@SerializedName("updateDate")
final long updateDate;
private MyObject(final String serialNo, final String createBy, final long createDate, final String updateBy, final long updateDate) {
this.serialNo = serialNo;
this.createBy = createBy;
this.createDate = createDate;
this.updateBy = updateBy;
this.updateDate = updateDate;
}
}
private static final TypeToken<List<MyObject>> listOfMyObjectTypeToken = new TypeToken<List<MyObject>>() {};
// ...
final List<MyObject> myObjects = toArrayList(jsonArray, listOfMyObjectTypeToken);
System.out.println(myObjects);
System.out.println(myObjects.get(0).getClass().getSimpleName());
传递类型标记为 Gson 提供了 足够 信息来处理要处理的类型。原因如下:
[MyObject(serialNo=1339497989051277312, createBy=xxxx, createDate=1608196182000, updateBy=xxxx, updateDate=1615444156000)]
MyObject