bbenet / json-path

Automatically exported from code.google.com/p/json-path
0 stars 0 forks source link

ArrayIndexFilter - Array Slicing Broken #21

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Run the following unit test
    public void testArrayIndexFilter()
    {
        ArrayIndexFilter filter = new ArrayIndexFilter("[1:]");

        Object obj = JsonLibrary.parseJson("[0,1,2,3]");
        JsonProvider provider = JsonProviderFactory.createProvider();
        Object value = filter.filter(obj, provider);
    }

What is the expected output? What do you see instead?

I expect 'value' to equal "[1,2,3]", but instead a NumberFormatException is 
raised.  I believe the problem is with the following line in ArrayIndexFilter:
trimmedCondition = trim(trimmedCondition.replace(" ", ""), 1, 1);
Shouldn't this be
trimmedCondition = trim(trimmedCondition.replace(" ", ""), 0, 1);

The way it is currently trimmedCondition = "" and clearly this is going to 
cause a NumberFormatException when passing to Integer.parseInt()

What version of the product are you using? On what operating system?
       <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path-assert</artifactId>
            <version>0.8.1</version>
        </dependency>

Additional Info:
-Can the Array Slice operator be implemented to adhere to the [start:end:step] 
convention.  Instead of just supporting [start:] and [:end], at the very least 
could it please support [start:end]
-Also I believe 'end' is supposed to be absolute and not relative to the length 
of the array.  If you want to do something relative to the end of the array I 
would suggest using negative values much like many other scripting languages 
(ie Python)

Python Example:
>>> array=[0,1,2,3]
>>> array[0:]
[0, 1, 2, 3]
>>> array[-1:]
[3]
>>> array[:-1]
[0, 1, 2]
>>> array[0:3:2]
[0, 2]
>>> array[1:3:2]
[1]
>>> array[1:4:2]
[1, 3]
>>> array[0:4]
[0, 1, 2, 3]

May I propose the following public Object filter(Object, JsonProvider) 
implementation that behaves the same as Python array slicing:

    public Object filter(Object obj,JsonProvider jsonProvider, String condition) {

        List<Object> src = jsonProvider.toList(obj);
        List<Object> result = jsonProvider.createList();

        // remove '[' and ']'
        String trimmedCondition = trim(condition, 1, 1);

        // resolve '@.length'
        trimmedCondition.replaceAll("@.length", new Integer(src.size()).toString());

        if(trimmedCondition.contains(":")){
            String[] tokens = trimmedCondition.split(":");

            int start = 0;
            int end = src.size() - 1;
            int step = 1;

            try{
                start = Integer.parseInt(tokens[0].trim());
                if(start < 0){
                    start = src.size() + start;
                }
            }
            catch(Exception ex){}

            if(tokens.length > 1){
                try{
                    end = Integer.parseInt(tokens[1].trim());
                    if(end < 0){
                        end = src.size() + end - 1;
                    }
                    else{
                        end -= 1;
                    }
                }
                catch(Exception ex){}
            }

            if(tokens.length > 2){
                try{
                    step = Integer.parseInt(tokens[2].trim());
                }
                catch(Exception ex){}
            }

            if(step <= 0){
                throw new RuntimeException("Step must be a positive value");
            }

            for(int i = start; i <= end; i+=step){
                result.add(src.get(i));
            }
            return result;
        }
        else {
            String[] indexArr = trimmedCondition.split(",");

            for (String idx : indexArr) {
                result.add(src.get(Integer.parseInt(idx.trim())));
            }
            return result;
        }
    }

Original issue reported on code.google.com by brut...@gmail.com on 1 Oct 2012 at 3:35

GoogleCodeExporter commented 8 years ago
Sorry I included the wrong pom snippet.  Here's the correct one

        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
            <version>0.8.1</version>
        </dependency>

Original comment by brut...@gmail.com on 1 Oct 2012 at 3:36

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
In version 0.9 (soon to be released) the operations below are supported

String JSON_ARRAY = "[1, 3, 5, 7, 8, 13, 20]";

JsonPath.read(JSON_ARRAY, "$[3]")     => 7              //no slicing    
JsonPath.read(JSON_ARRAY, "$[0,1,2]") => [1,3,5]        //no slicing, multi index
JsonPath.read(JSON_ARRAY, "$[:3]")    => [1,3,5]        //from index 0 (inclusive) 
until index 3 (exclusive)
JsonPath.read(JSON_ARRAY, "$[1:5]")   => [3, 5, 7, 8]   //from index 1 
(inclusive) until index 5 (exclusive)
JsonPath.read(JSON_ARRAY, "$[1:15]")  => IndexOutOfBoundsException
JsonPath.read(JSON_ARRAY, "$[-3:]")   => [8, 13, 20]    //from tail grab 3

JsonPath.read(JSON_ARRAY, "$[3:]")    => 8          //grab no 3 from tail
JsonPath.read(JSON_ARRAY, "$[(@.length -3)]") =>        //grab no 3 from tail (same 
as above) 

Original comment by kalle.st...@gmail.com on 20 Aug 2013 at 8:51