jsongroovyjsonslurper

Read Array name using JsonSlurper


I am new to the groovy language

I am trying to parse a JSON file using JsonSlurper in a groovy script. How can I access the names of the arrays in the JSON file below? i.e Array1 and Array2? And also so far I have only tried to declare a list using findall, but how do I declare the list without a condition?

def input = new JsonSlurper().parse(reader)
def items = input.Order.Items.findAll { item -> item.Valid == "true"}

Input:

{
  "Order": {
    "Header": {
      "OrderNumber": "ORD60001",
      "Date": "20190218"
    },
    "Array1": [
      {
        "ItemNumber": "10",
        "MaterialNumber": "MT70001",
        "Quantity": 57,
        "Valid": true
      },
      {
        "ItemNumber": "20",
        "MaterialNumber": "MT80001",
        "Quantity": 28,
        "Valid": false
      }
    ],
    "Array2": [
      {
        "ItemNumber": "10",
        "MaterialNumber": "MT70001",
        "Quantity": 57,
        "Valid": true
      },
      {
        "ItemNumber": "20",
        "MaterialNumber": "MT80001",
        "Quantity": 28,
        "Valid": false
      }
    ]
  }
}

Expected Output:

{
    "Order": {
        "Header": {
            "OrderNumber": "ORD60001",
            "Date": "20190218"
        },
        "Array1": [
            {
                "ItemNumber": "10",
                "MaterialNumber": "MT70001",
                "Quantity": 57,
                "Valid": true
            }
        ],
        "Array2": [
            {
                "ItemNumber": "10",
                "MaterialNumber": "MT70001",
                "Quantity": 57,
                "Valid": true
            }
        ]
    }
}

Solution

  • Ah I see now...

    You probably want something more like this:

    def filtered = [
        Order: new JsonSlurper().parse(reader)
                   .Order
                   .entrySet()
                   .collectEntries {
                       it.value instanceof List ?
                           [it.key, it.value.findAll { it.Valid }] :
                           it
                   }
    ]
    ​println new JsonBuilder(filtered).toPrettyString()
    

    Edit for the new structure:

    def validArrayEntries = input.Order.entrySet().findResults { entry ->
        // Go through all the orders, and find the ones that are lists
        if (entry.value instanceof List) {
    
            // Count the number of ones that are Valid
            def validEntries = entry.value.count { it.Valid }
    
            // If there are valid entries, then keep only them
            if (validEntries > 0) {
                [(entry.key): entry.value.findAll { it.Valid }]
            }
        }
    }.collectEntries() // This collects them back into a map
    
    // Then we can define our required JSON model               
    def model = [
        PurchaseOrder: [
            HeaderData: [ ID:  input.Order.Header.OrderNumber ],
    
            // And this injects the map from above into this map
            *:validArrayEntries
        ]
    ]
    
    def builder = new JsonBuilder(model).toPrettyString()
    
    

    I've commented the code, and tried to make it understandable, please let me know if it needs more explanation