json-path/JsonPath

BUG: cannot use nested expressions while using jackson as provider (Error casting ArrayNode to List)

Opened this issue · 7 comments

for example cant read this: "$.books[?(@.author_id in $.authors[?(@.name != "Jasson")]..author_id)]"

Using Configuration:
JacksonJsonNodeJsonProvider
JacksonMappingProvider

java.lang.ClassCastException: class com.fasterxml.jackson.databind.node.ArrayNode cannot be cast to class java.util.List (com.fasterxml.jackson.databind.node.ArrayNode is in unnamed module of loader 'app'; java.util.List is in module java.base of loader 'bootstrap')

at com.jayway.jsonpath.internal.filter.ValueNode$JsonNode.asValueListNode(ValueNode.java:341)

Hi. I would love to solve this issue.

Is your query correct? This works in 2.6.0

    @Test
    public void test() {
        String json = "{\n" +
                "      \"authors\": [\n" +
                "         {\n" +
                "            \"author_id\": 1,\n" +
                "            \"author\" : \"Nigel Rees\"\n" +
                "         },\n" +
                "         {\n" +
                "            \"author_id\": 2,\n" +
                "            \"author\" : \"Evelyn Waugh\"\n" +
                "         },\n" +
                "         {\n" +
                "            \"author_id\": 3,\n" +
                "            \"author\" : \"J. R. R. Tolkien\"\n" +
                "         }\n" +
                "      ],\n" +
                "      \"books\" : [\n" +
                "         {\n" +
                "            \"author_id\": 1,\n" +
                "            \"title\" : \"Sayings of the Century\"\n" +
                "         },\n" +
                "         {\n" +
                "            \"author_id\": 2,\n" +
                "            \"title\" : \"2-a\"\n" +
                "         },\n" +
                "         {\n" +
                "            \"author_id\": 2,\n" +
                "            \"title\" : \"2-b\"\n" +
                "         },\n" +
                "         {\n" +
                "            \"author_id\": 3,\n" +
                "            \"title\" : \"The Lord of the Rings\"\n" +
                "         }\n" +
                "      ]\n" +
                "}";

        List<String> result = JsonPath.using(JACKSON_CONFIGURATION)
                        .parse(json)
                        .read("$.books[?(@.author_id IN $.authors[?(@.author == \"Evelyn Waugh\")].author_id)].title");

        assertThat(result).containsExactly("2-a", "2-b");
    }

@kallestenflo you RIGHT!
I upgraded to 2.6.0 and it works

Thanks a lot!
Roey

@kallestenflo we are experiencing same issue on json-path version 2.7.0.

In json-path 2.7, com.jayway.jsonpath.JsonPath#put method is extended with this block of code:

if (evaluationContext.getPathList().isEmpty()) { boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS); if (optSuppressExceptions) { return handleMissingPathInContext(configuration); } else { throw new PathNotFoundException(); } }

In case when we want to suppress exceptions, com.jayway.jsonpath.JsonPath#handleMissingPathInContext method will fail, as it's tries to cast com.fasterxml.jackson.databind.node.ArrayNode to java.util.List.

In json-path version 2.6 com.jayway.jsonpath.JsonPath#resultByConfiguration method is used, which returns List, so there is no issue.

This issue is blocking us in migration to version of json-path 2.7.

having the same issue as @kallestenflo mentioned.
any workaround for this?

Hi. I'm facing the same issue here. Everything works fine in 2.6 (no need for Option.SUPPRESS_EXCEPTIONS), but fails in 2.7 (which requires Option.SUPPRESS_EXCEPTIONS in order for JsonPath#put not to fail on a missing path, as @nenad-kosanovic-tam pointed out).

For what it's worth, in my case the issue pops up when doing a put(), which fails in com/jayway/jsonpath/internal/JsonContext.java, at line 207:

    @Override
    public DocumentContext put(JsonPath path, String key, Object value) {
        List<String> modified = path.put(json, key, value, configuration.addOptions(Option.AS_PATH_LIST));

Here path.put(...) returns an ArrayNode, and the cast fails.

Is anyone able to find a workaround for this?