Java解析URL中多行JSON对象文件并转换为JSON数组的方法
解决方案:解析多行独立JSON对象(JSON Lines格式)
这是个典型的JSON Lines格式文件的解析问题——你的文件里每行都是一个独立的JSON对象,而不是标准的单一JSON数组,这就是为什么你用jp.parse(jr)只能读到第一个对象的原因,哪怕开了lenient模式也没用,因为parse()方法默认只会解析一个顶级JSON元素。
下面针对你正在使用的Gson库,给出两种可行的解决方案,同时补充Jackson的方案供你参考:
方案1:用Gson流式逐个读取顶级JSON对象
利用JsonReader的流式特性,循环检查并读取每个顶级对象,不需要依赖换行(但你的场景里换行也不影响):
URL url = new URL("你的文件URL"); URLConnection request = url.openConnection(); request.connect(); // 用try-with-resources自动关闭流 try (JsonReader jr = new JsonReader(new InputStreamReader((InputStream) request.getContent()))) { jr.setLenient(true); // 保留这个设置,兼容可能的小语法问题 JsonParser jp = new JsonParser(); // 循环读取直到文档结束 while (jr.peek() != JsonToken.END_DOCUMENT) { JsonElement jsonObj = jp.parse(jr); // 这里处理单个JSON对象:转成实体类、存入数据库等 System.out.println("读取到对象:" + jsonObj); } } catch (IOException e) { e.printStackTrace(); }
这段代码的核心是jr.peek()——它会提前查看下一个JSON token,只要还没到文档末尾,就继续解析下一个顶级对象,完美适配多顶级JSON的场景。
方案2:按行读取并单独解析(贴合你的“每行一个对象”场景)
既然每个JSON对象单独占一行,你可以直接按行读取文件,每行单独解析成JSON对象,这种方式还能方便地处理空行或解析失败的行:
URL url = new URL("你的文件URL"); URLConnection request = url.openConnection(); request.connect(); try (BufferedReader reader = new BufferedReader(new InputStreamReader((InputStream) request.getContent()))) { String line; JsonParser jp = new JsonParser(); while ((line = reader.readLine()) != null) { String trimmedLine = line.trim(); if (trimmedLine.isEmpty()) { continue; // 跳过空行 } try { JsonElement jsonObj = jp.parse(trimmedLine); // 处理对象、存入数据库 } catch (JsonSyntaxException e) { // 单独处理解析失败的行,比如打印日志 System.err.println("解析行失败:" + line); e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); }
可选:将所有对象合并为JSON数组
如果你后续需要把这些对象转成标准的JSON数组,不需要手动加逗号,直接用Gson的JsonArray收集即可:
JsonArray jsonArray = new JsonArray(); // 结合方案1的循环 while (jr.peek() != JsonToken.END_DOCUMENT) { JsonElement jsonObj = jp.parse(jr); jsonArray.add(jsonObj); } // 现在jsonArray就是包含所有对象的标准JSON数组了
补充:Jackson库的解决方案(如果后续考虑换库)
如果你使用Jackson库,它原生支持JSON Lines格式的解析,甚至可以直接映射到你的实体类:
URL url = new URL("你的文件URL"); URLConnection request = url.openConnection(); request.connect(); ObjectMapper mapper = new ObjectMapper(); // 读取流并逐个解析为你的实体类(替换成你自己的POJO类) try (InputStream inputStream = (InputStream) request.getContent()) { MappingIterator<YourEntityClass> iterator = mapper.readerFor(YourEntityClass.class).readValues(inputStream); while (iterator.hasNext()) { YourEntityClass obj = iterator.next(); // 存入数据库 } } catch (IOException e) { e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者Geo Thomas
相关产品推荐
相关产品推荐

