2

Using Powershell, I get a json snippet returned into my First variable (this always works fine);

# Initialise variables...
$nMessage_id = "";
$whatStatusJsonContent = "";
# Function https://abc.googleapis.com/abc/load call here and returns...
$whatStatusJsonContent = '{"message_id":9093813071099257562}'

Then I call the convert function into a temp variable like this;

$ResponseBody = ConvertFrom-Json $whatStatusJsonContent;

which puts the Json into a nice little data structure like this;

         message_id
         ----------
9093813071099257562

From which I can select the value I want by calling this;

$nMessage_id = $ResponseBody.message_id;

Usually, this works fine and I get the value into my second variable;

$nMessage_id = 9093813071099257562

The problem is: Sometimes I get nothing in $nMessage_id, even though $whatStatusJsonContent is definitely logged as having the Json returned correctly from the function.

My question is: Do I have to ConvertFrom-Json, or can I read it raw from the First variable..?

COMBINED SOLUTION: Thanks to @mklement() and @Bernard-Moeskops

# Initialise variables...
$nMessage_id = "";
$whatStatusJsonContent = "";
# Function https://abc.googleapis.com/abc/load call here and returns...
$whatStatusJsonContent = '{"message_id":9093813071099257562}'

$ResponseBody = ConvertFrom-Json $whatStatusJsonContent;

if($ResponseBody.message_id){
    # ConvertFrom-Json got the value!
    $nMessage_id = $ResponseBody.message_id
}else{
    # ConvertFrom-Json didn't work!
    $nMessage_id = = ($whatStatusJsonContent -split '[:}]')[1]
}
0

2 Answers 2

2

There's nothing overtly wrong with your code.

ConvertFrom-Json should work as expected and return a [pscustomobject] instance with a .message_id property.

In your example, the message_id JSON property value is a number that is an integer, for which ConvertTo-Json automatically chooses a suitable integer data type as follows: the smallest signed type >= [int] (System.Int32)[1] that can accommodate the value ([int] -> [long] (System.Int64) -> [decimal] (System.Decimal)); the caveat is that if the value can't even fit into a [decimal], an - inexact - [double] is used.[2]

With the sample JSON in your question, [long] is chosen.

In a follow-up comment you state:

The routine makes over 1000 calls/hour and for most of them the Json comes back and the $nMessage_id is yielded perfectly. Then, suddenly, the $nMessage_id is empty, even though the Json is logged as coming back fine. So, somewhere in the ConvertFrom-Json or $ResponseBody.message_id the value is going missing...

I have no explanation, but if - for whatever reason - ConvertFrom-Json is the culprit, you can try string manipulation as a workaround to extract the message ID and see if that helps:

$whatStatusJsonContent = '{"message_id":9093813071099257562}'

# Extract the message_id property value as a *string*  
# (which you can cast to a numeric type if/as needed).  
$message_id = ($whatStatusJsonContent -split '[:}]')[1]

The above stores a string with content 9093813071099257562 in $message_id; note that, as written, the input string must have the exact format as above with respect to whitespace; while it is possible to make the text parsing more robust, not having to worry about format variations is one good reason to use a dedicated parser such as ConvertFrom-Json.


Another option is to try a different JSON parser to see if that helps. Json.NET is the preeminent JSON parser in the .NET world (which now underlies the JSON cmdlets in PowerShell Core):

$whatStatusJsonContent = '{"message_id":9093813071099257562}'

$message_id = [NewtonSoft.Json.Linq.JObject]::Parse($whatStatusJsonContent).message_id.Value

Note: Json.NET - like ConvetFrom-Json in PowerShell _Core - commendably uses the arbitrary large [bigint] type as well once a number is too large to fit into a [long].

Use of the Json.NET assembly has the added advantage of better performance than the ConvertFrom-Json cmdlet.

In PowerShell Core, you can run the above code as-is (the assembly is preloaded); in Windows PowerShell you'll have to download the package via the link above and add the assembly (NewtonSoft.Json.dll) to your session with Add-Type -LiteralPath.


[1] Curiously, in PowerShell Core, as of (at least) v6.2.0, the smallest type chosen is [long] (System.Int64).

[2] More helpfully, PowerShell Core, as of (at least) v6.2.0, creates an arbitrarily large [bigint] (System.Numerics.BigInteger) instance once a value doesn't fit into a [long] anymore; that is, the [decimal] type is skipped altogether.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, @rangi; I'm glad you found a working solution. It would still be interesting to know the true cause of the problem, i.e., if there's a ConvertFrom-Json bug; have you tried the Json.NET alternative, so you don't have to rely on text parsing?
I will try that when I get a chance, it's a bit trickier because I may not be able to upload a package into the Azure serverless environment. Cheers!
1

You are going to have to convert it, so that PowerShell can understand it. It will convert from a string to a PSCustomObject. Just check by asking the type of the variable before and after.

$ResponseBody.message_id.GetType()

If sometimes the output is nothing, you could do something like:

if($ResponseBody.message_id){
    $nMessage_id = $ResponseBody.message_id
}else{
    throw "No message id found"
}

Hope this helps.

3 Comments

I highly doubt that that is the problem. I think it actually does not return any data at the times the variable is empty.. What you need to do is use Powershell_ise.exe and make sure to put something like the following in your script. # if(!$ResponseBody.message_id){Write-Host "The Response body is empty"} # Now place a brakepoint (F9) on the Write-Host section. Run the script, and as soon as the body is empty, you will hit the brakepoint. Now the script pauses and you can troubleshoot with the specific call which is empty. Hope this helps and let me know if i need to clarify further.
The only thing I can imagine is, because of a connection dropping or something, the response is empty every once in a million? times. The ConvertFrom-Json will always work when given valid input. If a certain program is written solid, it does not fail. However, making calls to an API has a lot of dependencies. In your case, it is very hard to troubleshoot. Network-related issues is the obvious to blame. You could try to gather more than just the $ResponseBody.message_id, for instance StatusCode and whenever it is different than e.g. 200 to output the response/error.
Thanks @Bernard-Moeskops for your help, see combined solution

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.