"Invalid JSON primitive" error when converting JSON file - json

When trying to convert a JSON file via PowerShell:
$json = Get-Content "C:\folder1\test.txt"
$json | ConvertFrom-Json
write-output $json
I'm getting the following error:
invalid json primitive : [.
(system.argunment.exception)

I'm going out on a limb here, since you didn't provide your input data or the complete error message, but I guess that your problem is caused by a format mismatch between the output Get-Content provides and the input ConvertFrom-Json expects.
Get-Content reads the input file into an array of strings, whereas ConvertFrom-Json expects the JSON data in a single string. Also, piping $json into ConvertFrom-Json does not change the value of $json.
Change your code to the following and the error should disapear (provided there is no syntactical error in your input data):
$json = Get-Content 'C:\folder1\test.txt' | Out-String | ConvertFrom-Json
Write-Output $json

You should check your JSON input file for characters that are not properly escaped with a "\"
I have also seen this issue with an input JSON file that was incorrectly formatted as follows:
{
Object1
}
{
Object2
}
Corrected format:
[{
Object1
},
{
Object2
}]
Once the format was corrected, I had no more issues.

I was also receiving this error, and upon investigating my json file noticed that some of the JSON was invalid. I was ending the last object in an array with a comma like so:
[{ ..},]
Removing the comma fixed the issue for myself.
So in short, invalid JSON caused this issue for me.

You will get this error if your input data starts like this:
data: [
{
...
},
{
...
}
]
You need to remove data: (and only have [and ] in this example):
[
{
...
},
{
...
}
]

Related

Inputting JSON data in Powershell

Currently, I'm attempting to call upon an API to run a POST, with JSON data as the body. So I was wondering if anyone would be able to tell me how I need to format the text below inside the variable $postParams. I'm pretty new at working with JSON so I'm having so trouble with this.
Currently, I only have the following and don't know what to do about the second line on.
$postParams = #{name='Example'}
Here's is the entire data I was hoping to add to $postParams. So if you could help me with the 2nd, 4th, and 8th that'd be awesome. Thanks!
{
"name":"Example",
"template":{"name":"Template"},
"url":"http://localhost",
"page":{"name":"Landing Page"},
"smtp":{"name":"Sending Profile"},
"launch_date":"2019-10-08T17:20:00+00:00",
"send_by_date":null,
"groups":[{"name":"test group"}]
}
You'll need a here-string and ConvertFrom-Json.
here-string:
Quotation marks are also used to create a here-string. A here-string is a single-quoted or double-quoted string in which quotation marks are interpreted literally. A here-string can span multiple lines. All the lines in a here-string are interpreted as strings, even though they are not enclosed in quotation marks.
The resulting code:
# Use a PowerShell here string to take JSON as it is
$jsonString = #"
{
"name":"Example",
"template":{"name":"Template"},
"url":"http://localhost",
"page":{"name":"Landing Page"},
"smtp":{"name":"Sending Profile"},
"launch_date":"2019-10-08T17:20:00+00:00",
"send_by_date":null,
"groups":[{"name":"test group"}]
}
"#
# Pipe the string to create a new JSON object
$jsonObject = $jsonString | ConvertFrom-Json
# The resulting JSON object has properties matching the properties in the orig. JSON
$jsonObject.name
$jsonObject.url
# Nested property
$jsonObject.template.name
# Nested property in array
$jsonObject.groups[0].name
I've posted an online version of the above code at tio.run, so you can play around with it.
If you want to update several properties of the $jsonObject you can do the following:
$jsonObject.name = "NEW NAME"
$jsonObject.url = "NEW URL"
$jsonObject | ConvertTo-Json
ConvertTo-Json will take your object and create an appropriate JSON string:
{
"name": "NEW NAME",
"template": {
"name": "Template"
},
"url": "NEW URL",
"page": {
"name": "Landing Page"
},
"smtp": {
"name": "Sending Profile"
},
"launch_date": "2019-10-08T17:20:00+00:00",
"send_by_date": null,
"groups": [
{
"name": "test group"
}
]
}
If you $jsonObject has more than two levels of depth, use the -Depth parameter, otherwise not all object information will be included in the JSON string.
ConvertTo-Json:
-Depth
Specifies how many levels of contained objects are included in the JSON representation. The default value is 2.
Here is a tio.run link to a ConvertTo-Json example.
Hope that helps.
I can't test it currently, but try this.
$postParams = #'
{
"name":"Example",
"template":{"name":"Template"},
"url":"http://localhost",
"page":{"name":"Landing Page"},
"smtp":{"name":"Sending Profile"},
"launch_date":"2019-10-08T17:20:00+00:00",
"send_by_date":null,
"groups":[{"name":"test group"}]
}
'#
Make a hashtable, then convert to JSON:
$Hashtable = #{
Key1 = "Value1"
Key2 = "Value2"
}
$Json = $Hashtable | ConvertTo-Json

How to make ConvertTo-Json not remove backslashes?

For this JSON file:
[
{
"Wildcard": "**\\\\*.Tests*.dll"
}
]
When I use ConvertFrom-Json on this file I get this:
Wildcard : **\\*.Tests*.dll
Note that it removed two of the backslashes from the original. I want powershell to keep these backslashes, so that when I output the powershell object back to a file using ConvertTo-Json, I see the 4 backslashes in the JSON.
How can I do this?
there is a function to unescape the 4 special characters like bashslashes
ConvertTo-Json | % { [System.Text.RegularExpressions.Regex]::Unescape($_) }

Decoding Base64 in only a portion of a JSON file with Powershell

I am making an API call on one of my vendor's applications via powershell. The response from the API is a JSON file. Only a portion of the JSON file is encoded in BASE64. Is there a way to read the JSON file with powershell and decode the section that is encoded in BASE64? Example of the JSON file:
I can manually copy the "meta" data from the json file and decode it with powershell using the following code:
[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String("BASE64DATA"))
however when I try to pass in the JSON file instead of the copied text I get an error.
{
results: [
{
"id": "<Plain Text Data>",
"meta": "<BASE64 Encoded Data>",
"info": "<Plain Text Data>"
},
{
"id": "<Plain Text Data>",
"meta": "<BASE64 Encoded Data>",
"info": "<Plain Text Data>"
}
]
}
You can have the json as an object, then convert it, decode and convert back to json.
$Json = Get-Content -Path c:\JsonFilePath.json | ConvertFrom-Json
$NewJson = $Json.Results | Foreach-Object -Process {
$Converted = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($_.meta))
$_.meta = $Converted
}
$NewJson | ConvertTo-Json
Since you're dealing with a RESTful API that returns JSON I recommend using the Invoke-RestMethod cmdlet to pull the data, it will automatically parse the JSON for you into an object.
Below is an example of how this would be done.
$json = Invoke-RestMethod -Uri 'https://something'
$json.results | ForEach-Object { $_.meta = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($_.meta)) }
$json.results
It will connect, pull the JSON data, and convert it to an object in the first command
The second command will convert the base64 encodings to plain text.
The third command will output the data for you to validate that this is working as expected.

Using Powershell to convert a file's contents into a string that can be transferred using JSON

How does one convert a text file's contents into a string and then insert this string into a JSON file?
For example, if a file contains:
this
is
a
sample
file
The script would generate:
"this\r\nis\r\na\r\nsample\r\nfile"
To insert into a JSON template:
"something":"<insertPoint>"
To produce:
"something":"this\r\nis\r\na\r\nsample\r\nfile"
I'm using Powershell 5 and have managed to load the file, generate some JSON and insert it by running:
# get contents and convert to JSON
$contentToInsert = Get-Content $sourceFilePath -raw | ConvertTo-Json
# write in output file
(Get-Content $outputFile -Raw).replace('<insertPoint>', $contentToInsert) | Set-Content $outputFile
However, a lot of other, unwanted fields are also added.
"something":"{
"value": "this\r\nis\r\na\r\nsample\r\nfile"
"PSPath": "C:\\src\\intro.md",
"PSParentPath": "C:\\src",
"PSChildName": "intro.md",
etc...
Ultimately, I'm trying to send small rich text segments to a web page via JSON but want to edit and store them locally using Markdown. If this doesn't make sense and there's a better way of sending these then please let me know also.
iRon's answer helpfully suggests not using string manipulation to create JSON in PowerShell, but to use hashtables (or custom objects) to construct the data and then convert it to JSON.
However, that alone does not solve your problem:
PS> #{ something = Get-Content -Raw $sourceFilePath } | ConvertTo-Json
{
"something": {
"value": "this\nis\na\nsample\nfile\n",
"PSPath": "/Users/mklement/Desktop/pg/lines.txt",
# ... !! unwanted properties are still there
}
The root cause of the problem is that Get-Content decorates the strings it outputs with metadata in the form of NoteProperty properties, and ConvertTo-Json currently invariably includes these.
A proposal to allow opting out of this decoration when calling Get-Content can be found in GitHub issue #7537.
Complementarily, GitHub issue #5797 suggests that ConvertTo-Json should ignore the extra properties for primitive .NET types such as strings.
The simplest workaround is to access the underlying .NET instance with .psobject.baseobject, which bypasses the invisible wrapper object PowerShell uses to supply the extra properties:
PS> #{ something = (Get-Content -Raw $sourceFilePath).psobject.baseobject } |
ConvertTo-Json
{
"something": "this\nis\na\nsample\nfile\n"
}
Just a general recommendation apart from the actually issue described by #mklement0 and metadata added to the Get-Content results:
Do not poke (replace, insert, etc.) in any Json content.
Instead, modify the object (if necessary, use ConvertFrom-Json to restore the object) prior converting it into (ConvertTo-Json) a Json file.
In this example, I would use a hash-table with a here-string for this:
#{'something' = #'
this
is
a
sample
file
'#
} | ConvertTo-Json
Result:
{
"something": "this\nis\na\nsample\nfile"
}
You can use the Out-String cmdlet to coerce the output of Get-Content into a flat string first:
#{ "something" = (Get-Content lines.txt | Out-String) } | ConvertTo-Json
This produces:
{
"something": "this\r\nis\r\na\r\nsample\r\nfile\r\n"
}

Powershell: Get value of a raw JSON

I have a JSON file which looks like this:
{
"body": {
"mode": "raw",
"raw": "{\n \"id\": \"middleware://so/998655555{{sguid}}\",\n \"reference\": \"998655555{{sguid}}\",\n \"branchCode\": \"1234\"\n }"
}
}
Now, I want to output the value of e.g. "branchCode".
I tried it with the following PowerShell commands:
$path = "file.json"
$raw = Get-Content $path -raw
$obj = ConvertFrom-Json $raw
$obj.body.raw.branchCode
Unfortunately, I don't get the value. It seems like PowerShell has a problem to retrieve the value from the raw json.
I would be very happy if someone could help me.
The value of "raw" is itself JSON.
You have to convert from JSON twice.
$data = Get-Content "file.json" -Raw -Encoding UTF8 | ConvertFrom-Json
$body = $data.body.raw | ConvertFrom-Json
$body.branchCode
prints
1234
Note that you should always explicitly specify an encoding when reading from and writing to text files. For the purposes of JSON (and, frankly, for pretty much every other purpose), UTF-8 is the appropriate choice.
Unfortunately Get-Content/Set-Content do not default to UTF-8. Save yourself from trouble by always specifying an encoding when working with text files.