'How to create a JSON body with PowerShell which is Deserializable by .NET6 when using az rest to call a .NET6 Azure Function

We are using AzureCLI to be able to call an Azure Function endpoint upon a successful deployment. The call to get token works and the call to our azure function makes it into MyFunction.

The problem is the format of the body when it arrives.

If we include the -Compress for ConvertTo-Json, the body arrives like {ResourceId:3,BuildPipelineName:ResourceName} and System.Text.Json.JsonSerializer.Deserialize throws 'R' is an invalid start of a property name. Expected a '"'. LineNumber: 0 | BytePositionInLine: 1.

If we don't include the -Compress for ConvertTo-Json, the body arrives like { and throws Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. LineNumber: 0 | BytePositionInLine: 1.

      runOnce:
        deploy:
          steps:
            - template: ./deployment.yml    

        on:  # On success or failure hook for runOnce deployment strategy
          success:  # Runs on success of all of the steps
            steps:
              - task: AzureCLI@2
                inputs:
                  azureSubscription: 'MyServiceConnectionName'
                  scriptType: ps
                  scriptLocation: inlineScript
                  inlineScript: |
                    $functionKeys = az functionapp function keys list -g my-resource-group -n my-azure-function-name --function-name MyFunction | ConvertFrom-Json
                    $defaultKey = $functionKeys.default
                    
                    $body = @{ 
                        ResourceId="$(Environment.ResourceId)";
                        ResourceName="$(Environment.ResourceName)";
                        } | ConvertTo-Json -Compress 
                    echo body: $body

                    $url2 = "https://my-azure-function-name.azurewebsites.net/api/MyFunction?code=$defaultKey"

                    $response = az rest --method post --uri $url2 --skip-authorization-header --verbose --body $body
                    echo response: $response

We've tried adding the following json options to JsonSerializer.Deserialize but with no change in behavior

        var jsonOptions = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true,
            ReadCommentHandling = JsonCommentHandling.Skip,
            AllowTrailingCommas = true,
            NumberHandling = JsonNumberHandling.AllowReadingFromString
        };

We've also tried changing the body creation to be a single line like:

  $body = @{ResourceId="$(Environment.ResourceId)";ResourceName="$(Environment.ResourceName)" } | ConvertTo-Json -Compress

We are new to both PowerShell and .NET6. We will gladly attempt changes on either side. Anything that may make this request succeed will be much appreciated.

Thank you for sharing your hard earned knowledge.



Solution 1:[1]

Az rest is very sensitive about the format of JSON input. For example, it requires double quotes to be escaped, even on Windows. It also doesn't like newlines, as you already noticed.

Try this way:

$body = (@{
  ResourceId="$(Environment.ResourceId)";
  ResourceName="$(Environment.ResourceName)";
} | ConvertTo-Json -Compress).Replace('"', '\"')

This will escape double quotes (bash style).

I would also recommend changing scriptType to pscore in your pipeline (it's supported on both Windows and Linux agents).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 qbik