Java 解析航班上的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();

我正在使用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();
        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),我想知道在解析期间是否可以在航班上执行插入,而不是等待计算数组的值。我在文档中看到可能可以完成这项工作,但我不知道如何使用它。

我有两个建议:

  • 在3行中反序列化整个集合:

        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秒。对于此更新,我将尝试它。不过,你可以打电话给我吗