Azure / azure-functions-powershell-worker

PowerShell language worker for Azure Functions.
MIT License
203 stars 52 forks source link

[PowerShell 7.4 Breaking Change] Document case-sensitivity breaking change #909

Open Francisco-Gamino opened 1 year ago

Francisco-Gamino commented 1 year ago

In PowerShell 7.0 and 7.2, ConvertFromJson returns a case-sensitive hashtable by design. In Azure Functions PowerShell 7.0 and 7.2, we take the output of ConvertFromJson and try to cast it to a case-insensitive hashtable to support deserializing JSON which may contain keys that only differ in case.

Starting PowerShell 7.3 or higher, the output of ConvertFromJson returns an ordered hashtable. The constructor of OrderedHashtable does not support creating a case-insensitive ordered hashtables. As a result, in Azure Functions PowerShell 7.4, we will no longer wrap the output of ConvertFromJson, so the return type will be an OrderedHashtable. This is a breaking change.

For users that need to be able to deserialize JSON with keys that only differ in case, we will provide a cmdlet as part of the Azure.Functions.PowerShell.SDK.

AnatoliB commented 1 month ago

The most visible user-facing consequence is that $Request.Body members in HTTP-triggered functions have case-sensitive names in PS 7.4, but they were case-insensitive in PS 7.2 and older. As a result, if a function receives an HTTP request like this:

{
    "name": "John"
}

both $Request.Body.Name and $Request.Body.name in the app code would correctly retrieve the "John" value. However, starting from PS 7.4, $Request.Body.Name will not retrieve the value anymore.

The reason is that automatic conversions from JSON match the behavior of the ConvertFrom-Json PowerShell cmdlet. This decision was intentional. As a result, the breaking change that happened in PowerShell 7.3 impacts PowerShell functions.

The original breaking change in PowerShell 7.3 (https://github.com/PowerShell/PowerShell/pull/17405) was called out in the docs (https://learn.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-73). For more context and future plans, see also this conversation: https://github.com/PowerShell/PowerShell/issues/19928

Workarounds

If you can control the HTTP client, make sure the names in the request match the names in the code precisely, including casing.

If you cannot control the HTTP client, convert $Request.Body to a case-insensitive data structure (for example, Hashtable):

$Request.Body = [HashTable]::New($Request.Body, [StringComparer]::OrdinalIgnoreCase)

Note: that you may need to do it recursively for nested JSON objects.

Documentation changes required