2

I'm reading an HTML file and need to pass it as a string parameter to a JSON call. The HTML has curly braces in it for css/styles. I was looking at this question, but mine is more around JSON special characters where that one was other escape characters. The file may also have [] characters.

$HtmlFromFile2 = @"
<html>
    <style type="text/css">.LetterList {font-family:"arial"}</style>
    <body>
        To [firstname]:
        This is a normal body with special JSON characters. 
    </body>
</html>
"@
$HtmlFromFile2Stripped = $HtmlFromFile2.Replace("`r", "").Replace("`n", "").Replace("`t","") 
#$HtmlFromFileFixed = % { [System.Text.RegularExpressions.Regex]::Unescape($HtmlFromFile2Stripped) }
$HtmlFromFileFixed = $HtmlFromFile2Stripped.Replace("{","\{").Replace("}","\}")

Write-Host "After RegEx Fix"
Write-Host $HtmlFromFileFixed 

$templateID = "Test_Temp7"


$body = @"
{   "uuid": "$templateID",
    "subject": "My Email Subject",
    "body": "$HtmlFromFileFixed"
}
"@

# This also tests if our JSON is "well-formed", on extra or missing commas, braces, brackets, etc... 
$bodyJSON = ConvertFrom-Json $body 

# Write-Host $body

$params = @{
    Uri         = 'https://stage-tms.demo.com/templates/email'
    Headers     = $headers
    Method      = 'POST'
    Body        = "$body"
    ContentType = 'application/json'
}

#Invoke-RestMethod @params

I use the Convert-FromJSON as test. When that works, then usually the Invoke-RestMethod will work. When the Convert-FromJSON fails, the Invoke-RestMethod will come back with http statsu=400 and statusDescription="Bad Request".

Current Errors:

ConvertFrom-Json : Invalid object passed in, ':' or '}' expected. (137): {   "uuid": "FEMAImport_Home_Test_Temp7",
    "subject": "SBA Disaster Loan Assistance TestText",
    "body": "<html>    <style type="text/css">.sbaLetterList \{font-family:"arial"\}</style><body>    This is a 
normal body with special JSON characters. </body></html>"
}
At C:\Scripts\TestJSONEscapeBraces.ps1:38 char:13
+ $bodyJSON = ConvertFrom-Json $body
+             ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

Update 1: I did some more tests. I'm ending up with too may permutations of what works and what doesn't work. I can't include the entire HTML file I'm using; I need a technique to isolate errors and identify them. I was hoping ConvertFrom-JSON would do that for me.

From below, you can see different files I'm trying. The first one (the real file and the larger one fails both on the ConvertFrom-JSON and the REST/Post. The other two are now working.

 $HtmlBodyFilename = "$PSScriptRoot\Emailbody_Home.html" 
#$HtmlBodyFilename = "$PSScriptRoot\Emailbody_Home_SimpleTest.html" 
#$HtmlBodyFilename = "$PSScriptRoot\Emailbody_Home_SimpleTestWithBraces.html" 
    $HtmlFromFile = Get-Content $HtmlBodyFilename -Raw   #the -Raw option gets a string instead of an array of lins 
    $HtmlFromFileStripped = $HtmlFromFile.Replace("`r", "").Replace("`n", "").Replace("`t","") 

I'm now able to read and process a small simple test file with curly braces in it. But when I point to the real HTML file on disk, I get errors, and don't know how to isolate it. I was probably assuming it was the curly brace.

If I use the ConvertFrom-JSON and the real HTML file, I get: ConvertFrom-Json : Invalid object passed in, ':' or '}' expected. (143): { "uuid": "FEMAImport_HomeFile_Test_Temp3", "subject": etc...

Now, if I remove the "ConvertFrom-JSON" and use the real HTML File, I get this error from the SOAP request: "The request was aborted: The connection was closed unexpectedly." Of course one difference is that the file is much bigger, about 83KB.

Before now, I have been getting a lot of 400 "Bad Request" errors, which is a useless error. I need to know what is wrong with the request.

NealWalters
  • 17,197
  • 42
  • 141
  • 251
  • 4
    Why create the JSON manually in the first place? It's just a string, nothing special to it. `$bodyJSON = [pscustomobject]@{uuid=$templateID;subject="My Email Subject";body=$HtmlFromFile2} |ConvertTo-Json` – Mathias R. Jessen Oct 20 '21 at 14:04

2 Answers2

6

Let Powershell do all the work for you and don't build the JSON string yourself, use an object:

$body = ConvertTo-Json @{
    uuid = $templateID
    subject = "My Email Subject"
    body = Get-Content $HtmlBodyFilename -Raw
}

All special characters will be escaped automatically.

Credits to @Hazrelle, of course you don't even have to convert anything in this case, as Invoke-WebRequest will do that for you:

$params = @{
    Uri         = 'https://stage-tms.demo.com/templates/email'
    Headers     = $headers
    Method      = 'POST'
    Body        = @{
        uuid = $templateID
        subject = "My Email Subject"
        body = Get-Content $HtmlBodyFilename -Raw
    }
    ContentType = 'application/json'
}
marsze
  • 15,079
  • 5
  • 45
  • 61
  • I was getting 400 Bad Request if file has {} in it or even line breaks. – NealWalters Oct 20 '21 at 14:21
  • Data will be coming from a get-content from file. I simplified for the question to create some code that would reproduce. Like I said, I don't need the Convert-FromJSON, but it's a way to verify the data before doing the Invoke-WebMethod and getting the 400 error. Basically every time I get the 400, I have to go back to something simpler that did work, and figure out what the differences were. – NealWalters Oct 20 '21 at 14:27
  • It doesn't matter what you put in `$HtmlFromFile2`, you can read that directly from the file, it will be converted to JSON correctly, there shouldn't be any problems at all if you do this. Maybe, update your code, and then show us your new version if you still have any issues. – marsze Oct 20 '21 at 14:29
  • Please see Update 1 in my question, it was too large for comment. Thanks – NealWalters Oct 20 '21 at 14:54
  • @NealWalters From your update it seems to me that you are still creating the json the same way as you did before, and not using the right approach as pointed out in my answer. No "html cleanup" is required here. See my updated code, maybe this is more clear. – marsze Oct 20 '21 at 14:59
  • I think now I need to check with the vendor about the size of the data: Your way or my way is giving: The request was aborted: The connection was closed unexpectedly. – NealWalters Oct 20 '21 at 15:04
  • @NealWalters sounds like a different problem, yes – marsze Oct 20 '21 at 15:15
3

You even don't need to convert anything to Json. Invoke-WebRequest will do it.

$body = @{   
    uuid: $templateID,
    subject: "My Email Subject",
    body: $HtmlFromFileFixed
}
Invoke-WebRequest ... -Body $body
Hazrelle
  • 758
  • 5
  • 9
  • I was getting 400 Bad Request if file has {} in it or even line breaks. – NealWalters Oct 20 '21 at 14:21
  • if brackets are properly enclosed in "" this shouldn't be an issue. Here the list of characters to escape when loading the file. Backspace is replaced with \b Form feed is replaced with \f Newline is replaced with \n Carriage return is replaced with \r Tab is replaced with \t Double quote is replaced with \" Backslash is replaced with \\ – Hazrelle Oct 20 '21 at 16:20