From 11983cd9eb59b6ff108b0b6572bba3e2f02a9394 Mon Sep 17 00:00:00 2001 From: Mark Kraus Date: Sat, 4 Nov 2017 05:55:13 -0500 Subject: [PATCH 1/3] [Feature] Fix Single Value JSON null in Invoke-WebRequest --- .../Common/InvokeRestMethodCommand.Common.cs | 16 ++++++++++++++-- .../WebCmdlets.Tests.ps1 | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs index 4b6039cf198..ebfb0a328c4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs @@ -5,6 +5,7 @@ using System; using System.Management.Automation; using System.IO; +using System.Text.RegularExpressions; using System.Xml; namespace Microsoft.PowerShell.Commands @@ -168,28 +169,39 @@ private bool TryConvertToXml(string xml, out object doc, ref Exception exRef) private bool TryConvertToJson(string json, out object obj, ref Exception exRef) { + bool converted; try { ErrorRecord error; obj = JsonObject.ConvertFromJson(json, out error); + converted = true; + + if (null == obj) + { + string pattern = @"^\s*null\s*$"; + Match matches = Regex.Match(json, pattern); + converted = matches.Success; + } if (error != null) { exRef = error.Exception; - obj = null; + converted = false; } } catch (ArgumentException ex) { exRef = ex; + converted = false; obj = null; } catch (InvalidOperationException ex) { exRef = ex; + converted = false; obj = null; } - return (null != obj); + return converted; } #endregion diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index 2391a8bac98..b220ee07c39 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -2613,6 +2613,24 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { } + Context "Invoke-RestMethod Single Value JSON null support" { + BeforeAll { + $baseUrl = 'http://localhost:8081/PowerShell?test=response&contenttype=application/json&output=' + } + It "Invoke-RestMethod Supports a Single Value JSON null" { + $url = '{0}{1}' -f $baseUrl, 'null' + Invoke-RestMethod -Uri $url | Should Be $null + } + It "Invoke-RestMethod Supports a Single Value JSON null and ignores whitespace" { + $url = '{0}{1}' -f $baseUrl, " null " + Invoke-RestMethod -Uri $url | Should Be $null + $url = '{0}{1}' -f $baseUrl, " + null + " + Invoke-RestMethod -Uri $url | Should Be $null + } + } + BeforeEach { if ($env:http_proxy) { $savedHttpProxy = $env:http_proxy From f6e173b57856611fe34fe20427374c3b4c39e87f Mon Sep 17 00:00:00 2001 From: Mark Kraus Date: Sun, 5 Nov 2017 08:11:04 -0600 Subject: [PATCH 2/3] [Feature] Switch from Regex to JToken.Parse() --- .../Common/InvokeRestMethodCommand.Common.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs index ebfb0a328c4..a755b1d4d0b 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/InvokeRestMethodCommand.Common.cs @@ -5,8 +5,9 @@ using System; using System.Management.Automation; using System.IO; -using System.Text.RegularExpressions; using System.Xml; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace Microsoft.PowerShell.Commands { @@ -169,36 +170,43 @@ private bool TryConvertToXml(string xml, out object doc, ref Exception exRef) private bool TryConvertToJson(string json, out object obj, ref Exception exRef) { - bool converted; + bool converted = false; try { ErrorRecord error; obj = JsonObject.ConvertFromJson(json, out error); - converted = true; if (null == obj) { - string pattern = @"^\s*null\s*$"; - Match matches = Regex.Match(json, pattern); - converted = matches.Success; + // This ensures that a null returned by ConvertFromJson() is the actual JSON null literal. + // if not, the ArgumentException will be caught. + JToken.Parse(json); } if (error != null) { exRef = error.Exception; - converted = false; + obj = null; + } + else + { + converted = true; } } catch (ArgumentException ex) { exRef = ex; - converted = false; obj = null; } catch (InvalidOperationException ex) { exRef = ex; - converted = false; + obj = null; + } + catch (JsonException ex) + { + var msg = string.Format(System.Globalization.CultureInfo.CurrentCulture, WebCmdletStrings.JsonDeserializationFailed, ex.Message); + exRef = new ArgumentException(msg, ex); obj = null; } return converted; From d968c998627f482f18f3b0822533d588aecf5e3a Mon Sep 17 00:00:00 2001 From: Mark Kraus Date: Sat, 11 Nov 2017 12:16:20 -0600 Subject: [PATCH 3/3] [Feature] Address PR Feedback: use `n --- .../Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 index b220ee07c39..dc3bdce61ed 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 @@ -2624,9 +2624,7 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" { It "Invoke-RestMethod Supports a Single Value JSON null and ignores whitespace" { $url = '{0}{1}' -f $baseUrl, " null " Invoke-RestMethod -Uri $url | Should Be $null - $url = '{0}{1}' -f $baseUrl, " - null - " + $url = '{0}{1}' -f $baseUrl, " null `n" Invoke-RestMethod -Uri $url | Should Be $null } }