0

Im using Jayway JsonPath library version 2.4.0. Using indexOf function in jsonPath, ex. $.values[?(@.num.indexOf('101') != -1)].id

Its giving exception Arguments to function: 'indexOf' are not closed properly. But the same works on online jsonPath evaluator

I've tried the same jsonPath & json string on https://jsonpath.com. It works fine there. I've tried some mix & match(ex. $.values[?(@.num.indexOf("101") != -1)].id) (double quote instead of single) but still same.

public static void main(String[] args) {
        try {
        String jsonString ="{ \n" + 
                "   \"values\":[ \n" + 
                "      { \n" + 
                "         \"num\":[\"101\", \"102\"],\n" + 
                "         \"id\": \"a\"\n" + 
                "      },\n" + 
                "       { \n" + 
                "         \"num\":[\"104\", \"105\"],\n" + 
                "         \"id\": \"b\"\n" + 
                "      }\n" + 
                "   ]\n" + 
                "}";



        String jsonPath = "$.values[?(@.num.indexOf('101') != -1)].id";


        DocumentContext jsonContext = JsonPath.parse(jsonString);
        List<String> ans = null;
        ans = jsonContext.read(String.valueOf(jsonPath));
        System.out.println(ans);
        }catch(Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

Expected answer is "a" but it gives exception. Here is the stacktrace

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
com.jayway.jsonpath.InvalidPathException: Arguments to function: 'indexOf' are not closed properly.
    at com.jayway.jsonpath.internal.path.PathCompiler.parseFunctionParameters(PathCompiler.java:375)
    at com.jayway.jsonpath.internal.path.PathCompiler.readPropertyOrFunctionToken(PathCompiler.java:217)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:151)
    at com.jayway.jsonpath.internal.path.PathCompiler.readDotToken(PathCompiler.java:171)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:145)
    at com.jayway.jsonpath.internal.path.PathCompiler.readPropertyOrFunctionToken(PathCompiler.java:237)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:151)
    at com.jayway.jsonpath.internal.path.PathCompiler.readDotToken(PathCompiler.java:171)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:145)
    at com.jayway.jsonpath.internal.path.PathCompiler.readContextToken(PathCompiler.java:124)
    at com.jayway.jsonpath.internal.path.PathCompiler.compile(PathCompiler.java:58)
    at com.jayway.jsonpath.internal.path.PathCompiler.compile(PathCompiler.java:75)
    at com.jayway.jsonpath.internal.filter.ValueNodes$PathNode.<init>(ValueNodes.java:580)
    at com.jayway.jsonpath.internal.filter.ValueNode.createPathNode(ValueNode.java:208)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readPath(FilterCompiler.java:364)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readValueNode(FilterCompiler.java:96)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readExpression(FilterCompiler.java:190)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readLogicalANDOperand(FilterCompiler.java:186)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readLogicalAND(FilterCompiler.java:150)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readLogicalOR(FilterCompiler.java:132)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readLogicalANDOperand(FilterCompiler.java:181)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readLogicalAND(FilterCompiler.java:150)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.readLogicalOR(FilterCompiler.java:132)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.compile(FilterCompiler.java:78)
    at com.jayway.jsonpath.internal.filter.FilterCompiler.compile(FilterCompiler.java:54)
    at com.jayway.jsonpath.internal.path.PathCompiler.readFilterToken(PathCompiler.java:461)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:141)
    at com.jayway.jsonpath.internal.path.PathCompiler.readPropertyOrFunctionToken(PathCompiler.java:237)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:151)
    at com.jayway.jsonpath.internal.path.PathCompiler.readDotToken(PathCompiler.java:171)
    at com.jayway.jsonpath.internal.path.PathCompiler.readNextToken(PathCompiler.java:145)
    at com.jayway.jsonpath.internal.path.PathCompiler.readContextToken(PathCompiler.java:124)
    at com.jayway.jsonpath.internal.path.PathCompiler.compile(PathCompiler.java:58)
    at com.jayway.jsonpath.internal.path.PathCompiler.compile(PathCompiler.java:75)
    at com.jayway.jsonpath.JsonPath.<init>(JsonPath.java:97)
    at com.jayway.jsonpath.JsonPath.compile(JsonPath.java:463)
    at com.jayway.jsonpath.internal.JsonContext.pathFromCache(JsonContext.java:222)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:78)
    at Init.main(Init.java:32)
Arguments to function: 'indexOf' are not closed properly.
abhijeet104
  • 486
  • 4
  • 9

1 Answers1

4

There are a number of implementations of JsonPath out there. Your path expression is incompatible with the Jayway implementation. I think this is a bug in that implementation.

So you can either switch libraries, or you can change your expression to something that the Jayway version is ok with. If you change your path to this, your code should give you the result you expect:

String jsonPath = "$.values[?('101' in @.num)].id";
CryptoFool
  • 21,719
  • 5
  • 26
  • 44