如何使用Jackson在Java中高效地从JSON文件中读取数据? [英] How do I read a data from a JSON file with high efficiency in Java with Jackson?
问题描述
我将所有静态数据存储在JSON
文件中.该JSON
文件最多具有1000
行.如何在不将所有行存储为ArrayList
的情况下获取所需的数据?
I store all static data in the JSON
file. This JSON
file has up to 1000
rows. How to get the desired data without storing all rows as ArrayList
?
我的代码,我现在正在使用,我想提高其效率.
My code, I'm using right now and I want to increase its efficiency.
List<Colors> colorsList = new ObjectMapper().readValue(resource.getFile(), new TypeReference<Colors>() {});
for(int i=0; i<colorsList.size(); i++){
if(colorsList.get(i).getColor.equals("Blue")){
return colorsList.get(i).getCode();
}
}
有可能吗?我的目标是在不使用ArrayList
的情况下提高效率.有没有办法像这样编写代码?
Is it possible? My goal is to increase efficiency without using ArrayList
. Is there a way to make the code like this?
Colors colors = new ObjectMapper().readValue(..."Blue"...);
return colors.getCode();
Resource.json
[
...
{
"color":"Blue",
"code":["012","0324","15478","7412"]
},
{
"color":"Red",
"code":["145","001","1","7879","123984","89"]
},
{
"color":"White",
"code":["7","11","89","404"]
}
...
]
Colors.java
class Colors {
private String color;
private List<String> code;
public Colors() {
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public List<String> getCode() {
return code;
}
public void setCode(List<String> code) {
this.code = code;
}
@Override
public String toString() {
return "Colors{" +
"color='" + color + '\'' +
", code=" + code +
'}';
}
}
推荐答案
在这种情况下创建POJO
类很浪费,因为我们不使用整个结果List<Colors>
,而只使用一个内部属性.为了避免这种情况,我们可以使用本机JsonNode
和ArrayNode
数据类型.我们可以使用readTree
方法读取JSON
,遍历数组,找到给定的对象,最后转换内部的code
数组.可能如下所示:
Creating POJO
classes in this case is a wasting because we do not use the whole result List<Colors>
but only one internal property. To avoid this we can use native JsonNode
and ArrayNode
data types. We can read JSON
using readTree
method, iterate over array, find given object and finally convert internal code
array. It could look like below:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
ArrayNode rootArray = (ArrayNode) mapper.readTree(jsonFile);
int size = rootArray.size();
for (int i = 0; i < size; i++) {
JsonNode jsonNode = rootArray.get(i);
if (jsonNode.get("color").asText().equals("Blue")) {
Iterator<JsonNode> codesIterator = jsonNode.get("code").elements();
List<String> codes = new ArrayList<>();
codesIterator.forEachRemaining(n -> codes.add(n.asText()));
System.out.println(codes);
break;
}
}
}
}
上面的代码显示:
[012, 0324, 15478, 7412]
该解决方案的缺点是我们将整个JSON
加载到内存中,这可能对我们来说是个问题.让我们尝试使用 Streaming API
来做到这一点.使用它有点困难,您必须知道JSON
有效负载的构造方式,但这是使用Jackson
获取code
数组的最快方法.下面的实现是幼稚的,不能处理所有可能性,因此您不应该依赖它:
Downside of this solution is we load the whole JSON
to memory which could be a problem for us. Let's try to use Streaming API
to do that. It is a bit difficult to use and you must know how your JSON
payload is constructed but it is the fastest way to get code
array using Jackson
. Below implementation is naive and does not handle all possibilities so you should not rely on it:
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
System.out.println(getBlueCodes(jsonFile));
}
private static List<String> getBlueCodes(File jsonFile) throws IOException {
try (JsonParser parser = new JsonFactory().createParser(jsonFile)) {
while (parser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = parser.getCurrentName();
// Find color property
if ("color".equals(fieldName)) {
parser.nextToken();
// Find Blue color
if (parser.getText().equals("Blue")) {
// skip everything until start of the array
while (parser.nextToken() != JsonToken.START_ARRAY) ;
List<String> codes = new ArrayList<>();
while (parser.nextToken() != JsonToken.END_ARRAY) {
codes.add(parser.getText());
}
return codes;
} else {
// skip current object because it is not `Blue`
while (parser.nextToken() != JsonToken.END_OBJECT) ;
}
}
}
}
return Collections.emptyList();
}
}
上面的代码显示:
[012, 0324, 15478, 7412]
最后,我需要提及有关 JsonPath
解决方案,它也可能很好如果可以使用其他库:
At the end I need to mention about JsonPath
solution which also can be good if you can use other library:
import com.jayway.jsonpath.JsonPath;
import net.minidev.json.JSONArray;
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
JSONArray array = JsonPath.read(jsonFile, "$[?(@.color == 'Blue')].code");
JSONArray jsonCodes = (JSONArray)array.get(0);
List<String> codes = jsonCodes.stream()
.map(Object::toString).collect(Collectors.toList());
System.out.println(codes);
}
}
上面的代码显示:
[012, 0324, 15478, 7412]
这篇关于如何使用Jackson在Java中高效地从JSON文件中读取数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!