Java 解析航班上的JSON
我正在使用GoogleGSONAPI为我的Android项目解析JSON文件,但我有一个性能问题 以下是我使用google GSON API解析JSON的源代码:Java 解析航班上的JSON,java,android,json,Java,Android,Json,我正在使用GoogleGSONAPI为我的Android项目解析JSON文件,但我有一个性能问题 以下是我使用google GSON API解析JSON的源代码: public void loadJsonInDb(String path){ InputStream isJson = context.getAssets().open(path); if (isJson != null) { int sizeJson = isJson.available();
public void loadJsonInDb(String path){
InputStream isJson = context.getAssets().open(path);
if (isJson != null) {
int sizeJson = isJson.available();
byte[] bufferJson = new byte[sizeJson];
isJson.read(bufferJson);
isJson.close();
String jsonStr = new String(bufferJson, "UTF-8");
JsonParser parser = new JsonParser();
JsonObject object = parser.parse(jsonStr).getAsJsonObject();
JsonArray array = object.getAsJsonArray("datas");
Gson gson = new Gson();
for(JsonElement jsonElement : array){
MyEntity entity = gson.fromJson(jsonElement, MyEntity.class);
// Do insert into Db stuffs
}
}
}
这方面的问题是,在解析之后,我必须使用for循环遍历JsonArray并执行所需的操作(即使用数组中每个元素的ORMLite插入SQLite DB),我想知道在解析期间是否可以在航班上执行插入,而不是等待计算数组的值。我在文档中看到可能可以完成这项工作,但我不知道如何使用它。我有两个建议:
Gson gson = new Gson();
Type listType = new TypeToken<ArrayList<MyEntity>>(){}.getType();
List<MyEntity> listOf = gson.fromJson(jsonStr, listType);
Gson-Gson=new-Gson();
Type listType=具有单个事务的新类型令牌李>
附言。
要使用bulkInsert
您必须从您的实体中创建ContentValues
列表。关于Gson和其他东西的使用,我有一些注意事项
- 您应该关闭
finally
块中的I/O资源,以确保没有资源泄漏(可用
和读取
可能会引发异常,阻止资源被关闭
d)。(另外,我不确定在这里使用available
是否是个好主意。)
- 在这种情况下,您不必使用
String
s。在这种情况下,字符串通常是性能/内存杀手(很大程度上取决于它们的结果大小),因为字符串会累积到内存中,因此,如果先将其全部收集到内存中,您将失去动态想法。在最坏的情况下,它会以OutOfMemoryError
结束应用程序
- 您可以使用指定的编码读取输入流,因此不需要字符串缓冲
JsonParser
旨在返回JSON树:JsonElement
在内存中包含整个JSON树。听起来和上面的字符串类似,对吗?这是另一个性能惩罚
- 创建
Gson
实例可能会有点昂贵(当然,这取决于如何比较),您可以将其实例化一次:它是线程安全的
JsonStreamParser
也不是一个选项,因为每个next()
都会在内存中生成另一个JSON树分支(同样,这取决于JSON文档及其$.datas
数组及其元素的大小)
Gson.fromJson
使用查找来查找最佳类型适配器,您可以向Gson
实例请求一次类型适配器,这样就不会再浪费时间进行查找了。类型适配器通常也是完全线程安全的,因此可以缓存
综上所述,您可以按如下方式实现它:
private static final Gson Gson=new Gson();
私有静态最终类型适配器myEntityTypeAdapter=gson.getAdapter(MyEntity.class);
private static void loadJsonInDb(最终字符串路径)
抛出IOException{
//Java 7语言特性可以轻松转换为Java 6 try/finally
//请注意如何修饰(包装)所有内容:从输入流(字节流)到读取器(字符流,这里是UTF-8)再到JSON读取器(更高级的字符读取器)
try(final-JsonReader-JsonReader=new-JsonReader(new-InputStreamReader(context.getAssets().open(path),“UTF-8”)){
//确保即将打开根对象
jsonReader.beginObject();
//并迭代每个对象属性
while(jsonReader.hasNext()){
//检查一下它的名字
最终字符串名称=jsonReader.nextName();
//另一个Java7语言特性
交换机(名称){
//是数据吗?
案例“数据”:
//使用其打开的数组令牌
jsonReader.beginArray();
//并迭代每个数组元素
while(jsonReader.hasNext()){
//将当前值作为MyEntity实例读取
final MyEntity MyEntity=myEntityTypeAdapter.read(jsonReader);
//现在做你想做的
}
//“关闭”阵列
jsonReader.endArray();
打破
违约:
//如果是“数据”以外的内容--只需跳过整个值--Gson将有效地完成它(我希望,不确定)
jsonReader.skipValue();
打破
}
}
//“关闭”对象
jsonReader.endObject();
}
}
简单地说,您只需要编写一个解析器来使用每个令牌。现在,有了以下JSON文档:
{
"object": {
},
"number": 2,
"array": [
],
"datas": [
{
"k": "v1"
},
{
"k": "v2"
},
{
"k": "v3"
}
]
}
上面的解析器将提取$.datas.*
只消耗尽可能少的资源。用System.out.println(myEntity.k)替换//现在在这里做你想做的事
代码>将产生:
v1
v2
v3
假设MyEntity
是final类MyEntity{final String k=null;}
。请注意,您也可以使用这种方法处理无限JSON文档。数据库插入可能是一个瓶颈。您使用内容提供商还是直接插入?是否使用beginTransaction()endTRansaction()?Indead DB插入是瓶颈之一,实际上我测量了处理时间。对于JSON解析:17秒,对于DB插入:50秒。这就是为什么我想在解析过程中在航班上的DB中插入数据,这将是一种并行处理(解析+DB插入)。我不使用beginTransaction或endTRansaction,它能提高性能吗?我有类似的问题。Json数组包含大约1000条记录。如果使用内容提供商,则插入时间约为1分钟。如果直接访问db(无内容提供商)并在单个事务中插入需要约10秒。对于此更新,我将尝试它。不过,你可以打电话给我吗