Java 如何使用Jackson将嵌套值从JSON数组解析到列表中

Java 如何使用Jackson将嵌套值从JSON数组解析到列表中,java,json,list,parsing,jackson,Java,Json,List,Parsing,Jackson,所以,我四处寻找这个答案,但我没有找到一个能反映我的情况的解决方案。基本上,我有一个JSON结构,看起来像: { "count": 4424, "results": [ {"id": 2718, "name": "fox", "location": "Omaha"}, {"id": 2719, "name": "bear", "location": "Miami"} ... more objects contain

所以,我四处寻找这个答案,但我没有找到一个能反映我的情况的解决方案。基本上,我有一个JSON结构,看起来像:

{
    "count": 4424,
    "results": [
        {"id": 2718, "name": "fox", "location": "Omaha"}, 
        {"id": 2719, "name": "bear", "location": "Miami"}
        ...
        more objects containing an ID field
        ...
    ]
}
我希望能够解析出所有的“id”值,并将它们存储在一个列表中,我将在该列表中循环,以对其他端点进行后续的REST调用。如果我想要包含id字段的整个对象,我知道我可以创建一个新对象并创建一个自定义JSON反序列化器,但是因为它只是我想要的一个字段,这感觉太过分了

我最初的想法是在自定义反序列化程序中执行某些操作,如下所示:

List<String> idList = new ArrayList<String>();
JsonNode node = jp.getCodec().readTree(jp); // jp = JsonParser
JsonNode resultsNode = node.get("results");
resultsNode.forEach(result -> {
    JsonNode idNode = result.get("id");
    if (idNode != null) {
        String id = idNode.textValue().toUpperCase();
        idList.add(id);
    }
});
List idList=new ArrayList();
JsonNode节点=jp.getCodec().readTree(jp);//jp=JsonParser
JsonNode resultsNode=node.get(“结果”);
resultsNode.forEach(结果->{
JsonNode idNode=result.get(“id”);
if(idNode!=null){
字符串id=idNode.textValue().toUpperCase();
idList.add(id);
}
});
这是正确的处理方法吗?如果不是,那么将这些id值解析为列表的最佳/有效方法是什么


另外,我在网上读到,在尝试这样的事情时,可能想进行缓存(列表可能包含1000多个ID),但我不太确定这在这个场景中意味着什么。有人能解释一下吗?

在没有尝试过的情况下,这看起来像是一个JSON文件,它可以从以下内容序列化Sightings对象

public AnimalSighting {
    public int id;
    public String name;
    public String location;
}
public Sightings {
    public int count;
    public ArrayList<AnimalSighting> results;
}
公共动物观察{
公共int id;
公共字符串名称;
公共字符串位置;
}
公众目击{
公共整数计数;
公共阵列列表结果;
}
然后使用
newObjectMapper().readValue(文件,Sightings.class)反序列化将非常简单


当然,这些类可以将私有属性与getter和setter一起使用,然后可能需要一些注释(@JsonCreator/@JsonProperty/@JsonGetter/@JsonSetter,具体取决于您正在做什么),但一般原则仍然是这样的。

如果您只需要
JSON
负载的一部分,则可以使用该库。下面您可以找到如何使用它的示例:

import com.jayway.jsonpath.JsonPath;

import java.io.File;
import java.util.List;

public class JsonPathApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        List<String> ids = JsonPath.read(jsonFile, "$.results.[*].id");
        System.out.println(ids);
    }
}
使用
Jackson
可以根据需要创建尽可能小的
POJO
模型:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
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();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        List<Id> ids = mapper.readValue(jsonFile, Response.class).getIds();
        System.out.println(ids);
    }
}

class Response {

    private final List<Id> ids;

    @JsonCreator
    public Response(@JsonProperty("results") List<Id> ids) {
        this.ids = ids;
    }

    public List<Id> getIds() {
        return ids;
    }
}

class Id {

    private final String id;

    @JsonCreator
    public Id(@JsonProperty("id") String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    @Override
    public String toString() {
        return id;
    }
}
如果我们不想映射所有属性,则需要此功能。它不应该比使用自定义反序列化程序的解决方案慢很多


1000+
JSON对象
在列表中不是一个很大的数字,也不应该是一个问题。您可以尝试为每个解决方案编写基准测试并比较结果。

所以我最初的想法是这样做,但就必须为JSON数组中的每个项创建一个新对象而言,这不是太过了吗,尤其是如果我不打算使用id之外的任何其他属性的话?解析字符串值并将其存储在列表中不是更好的性能吗?最终,您将拥有一个带有动物观察对象列表的Sightings对象。我看不出这怎么会比拥有一个字符串列表更“复杂”。或者我误解了你说的字符串值?id是否可以是字符串而不是示例中所示的整数?@Pr0pagate a
字符串
不是
对象
?如果问题是内存管理,将数据卸载到数据库中直到需要为止似乎是比将数据的转换字符串表示形式保存在内存中更好的解决方案。我刚刚测试了我的建议:反序列化一个包含1000万条目的JSON示例文件(该文件的大小约为1GB)大约需要10秒钟。因此,如果您“只有”1000多个条目,那么性能不应该太令人担忧。
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
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();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        List<Id> ids = mapper.readValue(jsonFile, Response.class).getIds();
        System.out.println(ids);
    }
}

class Response {

    private final List<Id> ids;

    @JsonCreator
    public Response(@JsonProperty("results") List<Id> ids) {
        this.ids = ids;
    }

    public List<Id> getIds() {
        return ids;
    }
}

class Id {

    private final String id;

    @JsonCreator
    public Id(@JsonProperty("id") String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    @Override
    public String toString() {
        return id;
    }
}
[2718, 2719]