Make ConvertFrom-Json deserialize an array of objects with multiple lines. (#3823)
* Fixing ConvertFrom-Json on CoreCLR to be able to handle a collection of strings which represent a JSON content. * Adding test case for ConvertFrom-Json to process an array of PSObjects as a single string.
This commit is contained in:
parent
40446c80a7
commit
7aa7f3858c
|
@ -72,8 +72,8 @@ namespace Microsoft.PowerShell.Commands
|
|||
protected override void EndProcessing()
|
||||
{
|
||||
// When Input is provided through pipeline, the input can be represented in the following two ways:
|
||||
// 1. Each input to the buffer is a complete Json content. There can be multiple inputs of this format.
|
||||
// 2. The complete buffer input collectively represent a single JSon format. This is typically the majority of the case.
|
||||
// 1. Each input in the collection is a complete Json content. There can be multiple inputs of this format.
|
||||
// 2. The complete input is a collection which represents a single Json content. This is typically the majority of the case.
|
||||
if (_inputObjectBuffer.Count > 0)
|
||||
{
|
||||
if (_inputObjectBuffer.Count == 1)
|
||||
|
@ -85,6 +85,7 @@ namespace Microsoft.PowerShell.Commands
|
|||
bool successfullyConverted = false;
|
||||
try
|
||||
{
|
||||
// Try to deserialize the first element.
|
||||
successfullyConverted = ConvertFromJsonHelper(_inputObjectBuffer[0]);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
|
@ -102,6 +103,7 @@ namespace Microsoft.PowerShell.Commands
|
|||
}
|
||||
else
|
||||
{
|
||||
// Process the entire input as a single Json content.
|
||||
ConvertFromJsonHelper(string.Join(System.Environment.NewLine, _inputObjectBuffer.ToArray()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Management.Automation;
|
||||
using System.Text.RegularExpressions;
|
||||
#if CORECLR
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
@ -42,11 +43,28 @@ namespace Microsoft.PowerShell.Commands
|
|||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
|
||||
error = null;
|
||||
#if CORECLR
|
||||
object obj = null;
|
||||
try
|
||||
{
|
||||
// JsonConvert.DeserializeObject does not throw an exception when an invalid Json array is passed.
|
||||
// This issue is being tracked by https://github.com/JamesNK/Newtonsoft.Json/issues/1321.
|
||||
// To work around this, we need to identify when input is a Json array, and then try to parse it via JArray.Parse().
|
||||
|
||||
// If input starts with '[' or ends with ']' (ignoring white spaces).
|
||||
if ((Regex.Match(input, @"(^\s*\[)|(\s*\]$)")).Success)
|
||||
{
|
||||
// JArray.Parse() will throw a JsonException if the array is invalid.
|
||||
// This will be caught by the catch block below, and then throw an
|
||||
// ArgumentException - this is done to have same behavior as the JavaScriptSerializer.
|
||||
JArray.Parse(input);
|
||||
|
||||
// Please note that if the Json array is valid, we don't do anything,
|
||||
// we just continue the deserialization.
|
||||
}
|
||||
|
||||
obj = JsonConvert.DeserializeObject(input, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None, MaxDepth = 1024 });
|
||||
|
||||
// JObject is a IDictionary
|
||||
|
|
|
@ -228,7 +228,6 @@ Describe "Json Tests" -Tags "Feature" {
|
|||
|
||||
# add a ScriptProperty called IsOld which returns whether the version is an older version
|
||||
$versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) }
|
||||
|
||||
$jstr = ConvertTo-Json $versionObject
|
||||
|
||||
# convert the JSON string to a JSON object
|
||||
|
@ -1455,4 +1454,25 @@ Describe "Json Bug fixes" -Tags "Feature" {
|
|||
{
|
||||
RunJsonTest $testCase
|
||||
}
|
||||
|
||||
It "ConvertFrom-Json deserializes an array of PSObjects (in multiple lines) as a single string." {
|
||||
|
||||
# Create an array of PSCustomObjects, and serialize it
|
||||
$array = [pscustomobject]@{ objectName = "object1Name"; objectValue = "object1Value" },
|
||||
[pscustomobject]@{ objectName = "object2Name"; objectValue = "object2Value" }
|
||||
|
||||
# Serialize the array to a text file
|
||||
$filePath = Join-Path $TESTDRIVE test.json
|
||||
$array | ConvertTo-Json | Out-File $filePath -Encoding utf8
|
||||
|
||||
# Read the object as an array of PSObjects and deserialize it.
|
||||
$result = Get-Content $filePath | ConvertFrom-Json
|
||||
$result.Count | Should be 2
|
||||
}
|
||||
|
||||
It "ConvertFrom-Json deserializes an array of strings (in multiple lines) as a single string." {
|
||||
|
||||
$result = "[1,","2,","3]" | ConvertFrom-Json
|
||||
$result.Count | Should be 3
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue