我有一个大的JSON文件(2.5MB),包含大约80000行。
它看起来像这样:
{
"a": 123,
"b": 0.26,
"c": [HUGE irrelevant object],
"d": 32
}
我只想为键a
、b
和d
存储整数值,并忽略JSON的其余部分(即忽略c
值中的任何内容)。
我无法修改原始JSON,因为它是由第三方服务创建的,我从其服务器下载。
如何在不将整个文件加载到内存中的情况下执行此操作?
我尝试使用gson库并创建了如下Bean:
public class MyJsonBean {
@SerializedName("a")
@Expose
public Integer a;
@SerializedName("b")
@Expose
public Double b;
@SerializedName("d")
@Expose
public Integer d;
}
但即使这样,为了使用Gson对它进行反序列化,我也需要先下载+读取内存中的整个文件,然后将其作为字符串传递给Gson?
File myFile = new File(<FILENAME>);
myFile.createNewFile();
URL url = new URL(<URL>);
OutputStream out = new BufferedOutputStream(new FileOutputStream(myFile));
URLConnection conn = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) conn;
InputStream in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
}
FileInputStream fis = new FileInputStream(myFile);
byte[] data = new byte[(int) myFile.length()];
fis.read(data);
String str = new String(data, "UTF-8");
Gson gson = new Gson();
MyJsonBean response = gson.fromJson(str, MyJsonBean.class);
System.out.println("a: " + response.a + "" + response.b + "" + response.d);
有没有什么方法可以避免加载整个文件,而只获得我需要的相关值?
3条答案
按热度按时间pbossiut1#
你一定要检查不同的方法和库。如果你真的关心性能检查:
Gson
,Jackson
和JsonPath
库来完成这个任务,并选择最快的一个。当然,你必须在本地磁盘上加载整个JSON
文件,可能是TMP
文件夹,然后解析它。简单的
JsonPath
解决方案可能如下所示:请注意,我没有创建任何
POJO
,只是使用类似于XPath
的JSONPath
特性读取给定值。我们不需要
JSONPath
,因为我们需要的值直接在root
节点中。如您所见,API
看起来几乎相同。我们还可以创建POJO
结构:即便如此,这两个库都允许直接从
URL
读取JSON
有效负载我建议使用您能找到的最佳方法在另一个步骤中下载它。Download a File From an URL in Java。unhi4e5o2#
有一些很好的库可以用最少的资源解析大的JSON文件。其中一个是流行的GSON library。它获得了将文件解析为流和对象的效果。它在每个记录通过时处理它,然后丢弃流,保持低内存使用。
如果您对使用GSON方法感兴趣,这里有一个很好的教程。Detailed Tutorial
gxwragnw3#
我只想存储键a、B和d的整数值,而忽略JSON的其余部分(即忽略c值中的任何内容)......如何在不将整个文件加载到内存中的情况下完成此操作?
一种方法是使用jq的所谓的流式解析器,通过--stream选项调用,这完全符合您的要求,但在空间和时间之间存在权衡,使用流式解析器通常更困难。
在当前情况下,例如,使用非流式(即,默认)解析器,可以简单地写:
使用流解析器,您必须编写如下内容:
或者,如果您愿意:
关于Java和jq的说明
虽然有针对jq的Java绑定(例如,请参见𝑸jq FAQ中的“:Java可以使用哪些语言绑定?”),但我不知道任何与--stream选项一起工作的绑定。
但是,由于2.5MB对于jq来说太小了,因此可以使用可用的Java-jq绑定之一,而不必使用流解析器。