powershell

Return value is different for calling and called methods in powershell


I'm experiencing a strange issue.

Here are my functions in the same order as in original script.

function Get-JsonFileContent {    
    param(        
        [System.Collections.ArrayList]$objects
    )

    $includeBlocks = [System.Collections.ArrayList]@();    

    if ($null -ne $objects -and $objects.ToString() -ne '' -and $objects.psobject.properties.count -gt 0) {
        foreach ($obj in $objects) {            
            if ($null -ne $obj -and $null -ne $obj.Name -and $obj.Name.Trim() -ne '' -and $obj.Name.Length -gt 0) {
                
                $include = @"
                {
                    "name": "$($obj.Name)",                    
                    "age": "$($obj.Age)"                                       
                }
"@
                $includeBlocks.Add($include);
            }            
        }
    } 
    $content = @"
    {
        "items": {
            "includes": [
                $($includeBlocks -join ",")
            ]
        }
    }
"@
    Set-Content -Force -Path "D:\one.json" -Value $content;
    return $content;
}

function GenerateJsonModule {    
    .....
    ....
    $jsonFileContent = Get-JsonFileContent -objects $objects;
    Set-Content -Force -Path "D:\two.json" -Value $jsonFileContent;
}

The output of one.json is as expected:

{
        "items": {
            "includes": [
                                {
                    "name": "John Doe",
                    "age": "30"                     
                },                {
                    "name": "Jane Doe",
                    "age": "40"                                      
                }
            ]
        }
    }

But two.json adds numbers as many as the count of "include" blocks, like this:

0
1
2
3
4
5
{
            "items": {
                "includes": [
                                    {
                        "name": "John Doe",
                        "age": "30"                     
                    },                {
                        "name": "Jane Doe",
                        "age": "40"                                      
                    }
                ]
            }
        }

Why is the same string output different for the called and the calling methods. What am I doing wrong here.


Solution

  • Those numbers are being generated inside of your first function Get-JsonFileContent every time the Add method of your array list is invoked.

    The line is $includeBlocks.Add($include). The Add method returns the index of the item you just added.

    The solution is to discard that return value. This can be done with the following: $includeBlocks.Add($include) | out-null.

    The reason that this is happening specifically when you invoke the first method from your second method is that PowerShell function returns are not strictly enforced. Anything placed into the pipeline by your function will be captured by whatever consumes the pipeline, not just the object which you explicitly place after the keyword return. Also note that those values are placed in the pipeline and consumed immediately rather than just when the function call completes.

    The reason you don't get those numbers when creating one.json is because, within function 1, you aren't exporting the return value of a function. You are simply building your object and exporting it.

    Function 2 is using the return from function 1, which contains all the data on the pipeline. In this case that is the numbers returned from the add method and the object you intended to return.

    If you check the type of the object returned by function 1, you will see that it is an array.