Search code examples
jenkinsgroovyyamlpipeline

Retrieving a value from YAML data in a Jenkins pipeline using Groovy


I am trying to improve the way I get values out of YAML data in Jenkins Groovy.

Example YAML:

---
customers:
  - customernumber: 477563
    first_name: Dorothy
    family_name: Gale
    order:
      - ordernumber : 876234786
        orderdate : 202501231456
        items:
        - part_no: A4786
          description: Water Bucket Filled
          price: 1.47
          quantity: 4
        - part_no: E1628
          description: High Heeled Ruby Slippers
          size: 8
          price: 133.7
          quantity: 1
  - customernumber: 6782545
    first_name: Fairy
    family_name: Godmother
    order:
      - ordernumber : 876234790
        orderdate : 202501271223
        items:
        - part_no: A5736
          description: Magic Wand
          price: 8.23
          quantity: 1
        - part_no: E7456
          description: Glitter 1Kg
          price: 13.99
          quantity: 1
        - part_no: A3524
          description: Axe
          price: 10.99
          quantity: 1

Example code to get a quantity value given a customer number, an order number, and a part number, ie a unique path into the YAML data :

String getQuantity(yamldata, customernumber, ordernumber, partnumber) {
    for (customernumber_item in yamldata.customers) {
        if (customernumber_item.customernumber == customernumber) {
            for (order_item in customernumber_item.order) {
                if (order_item.ordernumber == ordernumber) {
                    for (item_item in order_item.items) {
                        if (item_item.part_no == partnumber) {
                            return item_item.quantity
                        }
                    }
                }
            }
        }
    }
    // Default if the item wasn't found
    return null
}

<...>

YAMLDATA = readYaml(file: 'example.yaml')
quantity = getQuantity(YAMLDATA,'477563','876234786','E1628')

As you can see, I have a working function, but it is clumsy and very inefficient. There must be a more elegant, Groovy way?

Things I have tried:

  • GPaths, things like : quantity = YAMLDATA.customers*.customernumber['477563'].... I think I got close to a solution with GPaths, but this only seems to work if the leaf I'm looking for is at the end of the path. In this case it is not, it is in an adjacent path.

  • findAll. As far as I can see this won't work as there are potential duplicates of key value pairs in the YAML, and I really need the value at a specific leaf in a path in the YAML tree.

Thanks in advance.


Solution

  • So you could do this:

    println( yaml.customers.find { it.customernumber == 477563 }
        ?.order.find { it.ordernumber == 876234786 }
        ?.items.find { it.part_no == 'A4786' }
        ?.quantity )
    

    One thing I noticed is that customernumber and ordernumber are integers because they aren't surrounded by quotes in the YAML file and consist of all numbers. Once I figured that out the above expression worked.