Search code examples
groovygroovyshellgroovy-consolejenkins-groovy

Find/Filter the lists with a specific key-value pair from a JSON ARRAY (list of maps)


I have a JSON array (list of maps) similar to:

def listOfMap = [[TESTCASE:1, METHOD:'CLICK', RESULT:'PASS'], 
      [TESTCASE:2, METHOD:'CLICK', RESULT:'FAIL'], 
      [TESTCASE:3, METHOD:'CLICK', RESULT:'FAIL'], 
      [TESTCASE:4, METHOD:'TYPETEXT', RESULT:'FAIL']]

1) I want to get/filter/return all the lists that contain the key-value pairs "METHOD:CLICK" and "RESULT:FAIL"

My output should return 2 lists out of 4: [TESTCASE:2, METHOD:CLICK, RESULT:FAIL], [TESTCASE:3, METHOD:CLICK, RESULT:FAIL]

2) I want to get the count of lists that contain the key-value pairs "METHOD:CLICK" and "RESULT:FAIL"

My output should be : 2 

3) From the above list of maps, i want to get all the unique/distinct values for the key "METHOD"

My output should return unique values of the key method : CLICK, TYPETEXT

Solution

  • Filtering

    Groovy has a method called Collection.findAll(Closure closure) that filters out all values that don't satisfy a predicate (expressed as a closure):

    println listOfMap.findAll { map -> map.METHOD == 'CLICK' && map.RESULT == 'FAIL' }
    
    // Output: [[TESTCASE:2, METHOD:CLICK, RESULT:FAIL], [TESTCASE:3, METHOD:CLICK, RESULT:FAIL]]
    

    Counting

    There is also a method DefaultGroovyMethods.count(Iterable<T> self, Closure closure) that expects a predicate and count how many elements satisfy it:

    println listOfMap.count { map -> map.METHOD == 'CLICK' && map.RESULT == 'FAIL' }
    
    // Output: 2
    

    List of unique values from list of maps

    For selecting a value for given key from a list of maps you can use Groovy's spread operator:

    println listOfMap*.METHOD // btw, listOfMap.METHOD will do the same
    

    This code translates to "for each element inside listOfMap get me a value for key METHOD. In the next step you can use Collection.unique() method to remove all duplicates:

    println listOfMap*.METHOD.unique()
    
    // Output: [CLICK, TYPETEXT]
    

    WARNING: following method will not work in Jenkins pipeline Groovy script. In this case you will have to use Collection.collect(Closure closure) explicitly:

    println listOfMap.collect { map -> map.METHOD }.unique()