Invoke-RestMethod cmdlet error if the response is neither JSON nor XML (#2862)

* This change fixes the Invoke-RestMethod cmdlet behavior if the input is neither xml nor json.
* test description
* fixed the failed tests
* removed some duplication
* refactoring: eliminated some double castings
* added JsonObject unit tests; enhanced JSON deserialization exception message
* refactored JsonObject.Tests.ps1
* entitled test cases
* formatting
This commit is contained in:
Max Maximov
2016-12-15 00:06:26 -08:00
committed by Dongbo Wang
parent e26c2a8752
commit 8be31098b1
5 changed files with 79 additions and 16 deletions
@@ -92,12 +92,7 @@ namespace Microsoft.PowerShell.Commands
// The first input string does not represent a complete Json Syntax.
// Hence consider the the entire input as a single Json content.
}
#if CORECLR
catch (Newtonsoft.Json.JsonSerializationException)
{
// we use another serializer for CORECLR implementation
}
#endif
if (successfullyConverted)
{
for (int index = 1; index < _inputObjectBuffer.Count; index++)
@@ -44,20 +44,32 @@ namespace Microsoft.PowerShell.Commands
}
error = null;
#if CORECLR
object obj = JsonConvert.DeserializeObject(input, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None, MaxDepth = 1024 });
// JObject is a IDictionary
if (obj is JObject)
object obj = null;
try
{
obj = JsonConvert.DeserializeObject(input, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None, MaxDepth = 1024 });
// JObject is a IDictionary
var dictionary = obj as JObject;
obj = PopulateFromJDictionary(dictionary, out error);
if (dictionary != null)
{
obj = PopulateFromJDictionary(dictionary, out error);
}
else
{
// JArray is a collection
var list = obj as JArray;
if (list != null)
{
obj = PopulateFromJArray(list, out error);
}
}
}
// JArray is a collection
else if (obj is JArray)
catch (JsonException je)
{
var list = obj as JArray;
obj = PopulateFromJArray(list, out error);
var msg = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.JsonDeserializationFailed, je.Message);
// the same as JavaScriptSerializer does
throw new ArgumentException(msg, je);
}
#else
//In ConvertTo-Json, to serialize an object with a given depth, we set the RecursionLimit to depth + 2, see JavaScriptSerializer constructor in ConvertToJsonCommand.cs.
@@ -207,4 +207,7 @@
<data name="ReachedMaximumDepthAllowed" xml:space="preserve">
<value>The maximum depth allowed for serialization is {0}.</value>
</data>
<data name="JsonDeserializationFailed" xml:space="preserve">
<value>Conversion from JSON failed with error: {0}</value>
</data>
</root>
@@ -0,0 +1,46 @@
Describe 'Unit tests for JsonObject' -tags "CI" {
function ShouldThrow
{
param (
[Parameter(ValueFromPipeline = $true)]
$InputObject,
[Parameter(Position = 0)]
$ExpectedException
)
try
{
& $InputObject
throw "Should throw exception"
}
catch
{
$_.FullyQualifiedErrorId | should be $ExpectedException
}
}
$validStrings = @(
@{ name = "empty"; str = "" }
@{ name = "spaces"; str = " " }
@{ name = "object"; str = "{a:1}" }
)
It 'no error for valid string - <name>' -TestCase $validStrings {
param ($str)
$errRecord = $null
[Microsoft.PowerShell.Commands.JsonObject]::ConvertFromJson($str, [ref]$errRecord)
$errRecord | Should BeNullOrEmpty
}
$invalidStrings = @(
@{ name = "plain text"; str = "plaintext" }
@{ name = "part"; str = '{"a" :' }
)
It 'throw ArgumentException for invalid string - <name>' -TestCase $invalidStrings {
param ($str)
$errRecord = $null
{ [Microsoft.PowerShell.Commands.JsonObject]::ConvertFromJson($str, [ref]$errRecord) } | ShouldThrow 'ArgumentException'
}
}
@@ -635,4 +635,11 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
$result = ExecuteWebCommand -command $command
$result.Error | Should BeNullOrEmpty
}
It "Invoke-RestMethod supports request that returns plain text response." {
$command = "Invoke-RestMethod -Uri 'http://httpbin.org/encoding/utf8'"
$result = ExecuteWebCommand -command $command
$result.Error | Should BeNullOrEmpty
}
}