Как разобрать вложенное значение в список из массива JSON с помощью Jackson - PullRequest
0 голосов
/ 23 апреля 2019

Итак, я искал этот ответ, но не нашел решения, отражающего мою ситуацию.По сути, у меня есть структура 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);
    }
});

Это будет правильный способ справиться с этим?Если нет, то какой будет лучший / эффективный способ разбить эти значения идентификаторов в список?

Кроме того, я читал в Интернете о том, что, возможно, захочется выполнить кэширование при попытке чего-то подобного (список может содержать более 1000 идентификаторов).), но я не совсем уверен, что это значит в этом сценарии.Кто-нибудь сможет объяснить это?

Ответы [ 2 ]

1 голос
/ 24 апреля 2019

Если вам нужна только часть полезной нагрузки JSON, вы можете использовать библиотеку JsonPath . Ниже вы можете найти пример, как его использовать:

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);
    }
}

Над отпечатками кодов:

[2718,2719]

С помощью 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;
    }
}

Над отпечатками кодов:

[2718, 2719]

FAIL_ON_UNKNOWN_PROPERTIES функция требуется, если мы не хотим отображать все свойства. Он не должен быть намного медленнее, чем ваше решение с пользовательским десериализатором.

1000+ JSON objects в списке не так уж много и не должно быть проблемой. Вы можете попытаться написать тесты для каждого решения и сравнить результаты.

1 голос
/ 23 апреля 2019

Не пытаясь это сделать, это выглядит как JSON-файл, который будет получен в результате сериализации объекта Sightings из чего-то вроде

public AnimalSighting {
    public int id;
    public String name;
    public String location;
}
public Sightings {
    public int count;
    public ArrayList<AnimalSighting> results;
}

Тогда десериализация будет простой с new ObjectMapper().readValue(file, Sightings.class);

Конечно, классы могут использовать закрытые атрибуты с геттерами и сеттерами, а затем, возможно, потребуются некоторые аннотации (@ JsonCreator / @ JsonProperty / @ JsonGetter / @ JsonSetter, в зависимости от того, что именно вы делаете), но общий принцип остается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...