Add JSON file content to Invoke-WebRequest POST comment

How do I get a JSON file content to be passed in as the content in the below script?

$bodyFromJson = ‘{“comments”:[{“parentCommentId”:0,“content”:“<<JSON file content as comment>>”,“commentType”:1}],“properties”:{“Microsoft.TeamFoundation.Discussion.SupportsMarkdown”:{“type”:“System.Int32”,“value”:1}},“status”:1}’
$body = $bodyFromJson | ConvertTo-Json
$uri = “https://dev.azure.com/{organization}/{project}/_apis/wit/workItems/{workItemId}/comments?api-version=5.1-preview.3
$headers = @{
“Content-Type” = “application/json”
“Authorization” = “Bearer $env:SYSTEM_ACCESSTOKEN”
}
Invoke-WebRequest -Uri $Uri -Method Post -Headers $headers -Body ($body | ConvertTo-Json)

You can read the json file and put it inside.

$bodyFromJson = '{"comments":[{"parentCommentId":0,"content":' + $JsonContent + '","commentType":1}],"properties":{"Microsoft.TeamFoundation.Discussion.SupportsMarkdown":{"type":"System.Int32","value":1}},"status":1}'

Thanks. But by doing this way the json format is fully messed up though. How can I keep the same source format in the body as well?

Typically recommend using Powershell objects vs text as it gives you full flexibility:

temp.json

{
    "description": "My awesome description"
    "comment":"This is what I'm thinking"
}

Code:

$jsonFile = Get-Content -Path C:\Scripts\temp.json | ConvertFrom-Json

$body = [pscustomobject]@{
    comments = @(@{
        parentCommentId = 0
        content = $jsonFile
        commentType=1
    })
    properties = @{
        "Microsoft.TeamFoundation.Discussion.SupportsMarkdown" = @{
            type = "System.Int32"
            value = 1
        }
    }
    status = 1
}


$params = @{
    $headers = @{
        "Content-Type"  = "application/json"
        "Authorization" = "Bearer $env:SYSTEM_ACCESSTOKEN"
    }
    Uri    = "https://dev.azure.com/{organization}/{project}/_apis/wit/workItems/{workItemId}/comments?api-version=5.1-preview.3"
    Method = POST
    Body   = ($body | ConvertTo-Json)

}

Invoke-WebRequest @params

Body Output:

{
"comments":  [
                 {
                     "parentCommentId":  0,
                     "commentType":  1,
                     "content":  "@{description=My awesome description; comment=This is what I\u0027m thinking}"
                 }
             ],
"properties":  {
                   "Microsoft.TeamFoundation.Discussion.SupportsMarkdown":  {
                                                                                "value":  1,
                                                                                "type":  "System.Int32"
                                                                            }
               },
"status":  1

}

Thanks. Yes, it would have been easy if it was in the actual object instead of text. Unfortunately my json file is an output of a different task and is in text. Are there other options to maintain the formatting in the body? Below is the example of my json file content.

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place

Update will perform the following actions:

Resource ABC will be updated in-place

~ resource “resource_name” {
endpoint_name = “ABC”
endpoint_type = “xyz”
priority = 2
~ weight = 1 -> 10

custom_header {
name = “host”
value = “host.test.com
}
}

Plan: 0 to add, 1 to change, 0 to destroy.

If you want to preserve formatting in your json file, you should read the json as a single string and do not perform any serialization. If you want to append a json string to an existing one with minimal spacing, you should compress the json.
$jsonBody = ‘{“comments”:[{“parentCommentId”:0,“content”:“<<JSON file content as comment>>”,“commentType”:1}],“properties”:{“Microsoft.TeamFoundation.Discussion.SupportsMarkdown”:{“type”:“System.Int32”,“value”:1}},“status”:1}’
$myJson = @’
{
“Block1”: “value1”,
“Block2”: “value2”
}
'@

Inserting myJson as is into jsonBody

$jsonBody = $jsonBody -replace ‘<<JSON file content as comment>>’,$myJson

Inserting a compressed myJson into jsonBody

$myJsonCompressed = $myJson | ConvertFrom-Json | ConvertTo-Json -Depth 100 -Compress
$jsonBody = $jsonBody -replace ‘<<JSON file content as comment>>’,$myJsonCompressed

Reading Json as Single String from File to Preserve formatting

$jsonString = Get-Content file.json -Raw

Thanks guys. Getting closer…now i got the json format preserved by introducing the hash table instead but its failing when posting the values.

$JsonContent = Get-Content .\temp.json -Raw
$bodyFromJson = @{"comments"=@{"parrentCommentId"=0;"comment"=$JsonContent;"commentType"="1"};"properties"=@{"Microsoft.TeamFoundation.Discussion.SupportsMarkdown"=@{"type"="System.Int32";"value"="1"};"status"="1"}}
$body = $bodyFromJson | ConvertTo-Json
$uri = "https://dev.azure.com/uri"
$headers = @{
"Content-Type" = "application/json"
"Authorization" = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Invoke-WebRequest -Uri $Uri -Method Post -Headers $headers -Body $body

Getting the below error now

Line |
14 | Invoke-WebRequest -Uri $uri -Method Post -Body $body -Hea
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"$id":"1","innerException":null,"message":"Value cannot be
| null.\r\nParameter name:
| comments","typeName":"System.ArgumentNullException,
| mscorlib","typeKey":"ArgumentNullException","errorCode":0,"eventId":0}

            

When using ConvertTo-Json the default depth is 2. You need to add the -Depth parameter. I would just pick a high number like 10, something that will definitely be at or exceed your hierarchy level count.

I tried with -Depth 100 and still the same error.

Try this:

$JsonContent = Get-Content C:\Scripts\temp.json | ConvertFrom-Json
$bodyFromJson = @{"comments"=@{"parrentCommentId"=0;"comment"="";"commentType"="1"};"properties"=@{"Microsoft.TeamFoundation.Discussion.SupportsMarkdown"=@{"type"="System.Int32";"value"="1"};"status"="1"}}
$bodyFromJson.comments.comment = $JsonContent

$body = $bodyFromJson | ConvertTo-Json -Depth 10

$uri = "https://dev.azure.com/uri"

$headers = @{
    "Content-Type"  = "application/json"
    "Authorization" = "Bearer $env:SYSTEM_ACCESSTOKEN"
}

Invoke-WebRequest -Uri $Uri -Method Post -Headers $headers -Body $body

Rob, yes it would have been much more easier if the source json was well formatted. It is not and so convertfrom-json will fail. I pasted the json content above in my replies.

Nothing about the above is JSON. What part of this should be converted to JSON?

I basically prefer to have the content I pasted as an output of the body it the same format. Thats why I created a hash table and put all the above content as one string.