1

I have a JSON like this,

{
    "TotalCount": 2,
    "Data": [
        {
            "ID": 9663696221792,
            "Code": "08099991",
            "Items": [
                {
                    "Amount": 5.05,
                    "LineNo": 1
                },
                {
                    "Amount": 16.08,
                    "LineNo": 2
                }               
            ]
        },
        {
            "ID": 9663696221793,
            "Code": "08028001",
            "Items": [
                {
                    "Amount": 26.13,
                    "LineNo": 1
                }
            ]
        }
    ]

}

And I need the output to be like this,

row ID CODE Cost
header 9663696221792 08099991 21.13
Item 1 9663696221792 08099991 5.05
Item 2 9663696221792 08099991 16.08

and

row ID CODE Cost
Header 9663696221793 08028001 26.13
Item 1 9663696221793 08028001 26.13

and so on for more headers and items

so far $array = Get-Content -Path 'response.json' | ConvertFrom-Json

then I cycle through

foreach ($root in $array.data)

then though each item

foreach ($Item in $array.data.items)

however this cycles through all Items in the data array.

any ideas.

2
  • for the inner loop I think you want foreach ($Item in $root) or maybe foreach ($Item in $root.Items)? Commented Nov 26, 2024 at 19:13
  • 1
    That's it thanks Daniel Commented Nov 26, 2024 at 19:31

2 Answers 2

3
  • Indeed, the nested loop must refer to the outer loop's iteration variable rather than to the input object graph as a whole, as Daniel points out.

  • If you mistakenly access the whole object graph in the nested loop with $array.Data.Items, you perform member-access enumeration on the $array.Data array, meaning that the .Item property values across all array elements are returned.

To put it all together (variables renamed for clarity); note that member-access enumeration is still selectively used, namely in $product.Items.Amount in order to obtain the amounts across all .Item elements:

# Note: -Raw makes Get-Content much faster by reading the entire file
#       content into as single, multiline string.
$objectGraphfromJson = Get-Content -Raw response.json | ConvertFrom-Json

# Loop over all elements of the array in the `.Data` property.
foreach ($product in $objectGraphfromJson.Data) {
  # Create and output the header object.
  [pscustomobject] @{
    row = 'Header'
    ID = $product.ID
    Code = $product.Code
    # Sum up the amounts across all child items.
    Cost = ($product.Items.Amount | Measure-Object -Sum).Sum
  }
  # For each `.Data` element, loop over its items and 
  # create and output an object for each.
  foreach ($item in $product.Items) {
    [pscustomobject] @{
      row = 'Item ' + $item.LineNo
      ID = $product.ID
      Code = $product.Code
      Cost = $item.Amount
    }  
  }
}

Output (the equivalent of what you requested, based on PowerShell's automatic for-display formatting of the objects that were output):

row               ID Code       Cost
---               -- ----       ----
Header 9663696221792 08099991 21.130
Item 1 9663696221792 08099991  5.050
Item 2 9663696221792 08099991 16.080
Header 9663696221793 08028001 26.130
Item 1 9663696221793 08028001 26.130
Sign up to request clarification or add additional context in comments.

Comments

0

First loop

foreach ($root in $array.data)

Inside loop (inside the root loop)

foreach ($item in $root.items)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.