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()
|
protected override void EndProcessing()
|
||||||
{
|
{
|
||||||
// When Input is provided through pipeline, the input can be represented in the following two ways:
|
// 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.
|
// 1. Each input in the collection 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.
|
// 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 > 0)
|
||||||
{
|
{
|
||||||
if (_inputObjectBuffer.Count == 1)
|
if (_inputObjectBuffer.Count == 1)
|
||||||
|
@ -85,6 +85,7 @@ namespace Microsoft.PowerShell.Commands
|
||||||
bool successfullyConverted = false;
|
bool successfullyConverted = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Try to deserialize the first element.
|
||||||
successfullyConverted = ConvertFromJsonHelper(_inputObjectBuffer[0]);
|
successfullyConverted = ConvertFromJsonHelper(_inputObjectBuffer[0]);
|
||||||
}
|
}
|
||||||
catch (ArgumentException)
|
catch (ArgumentException)
|
||||||
|
@ -102,6 +103,7 @@ namespace Microsoft.PowerShell.Commands
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Process the entire input as a single Json content.
|
||||||
ConvertFromJsonHelper(string.Join(System.Environment.NewLine, _inputObjectBuffer.ToArray()));
|
ConvertFromJsonHelper(string.Join(System.Environment.NewLine, _inputObjectBuffer.ToArray()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Management.Automation;
|
using System.Management.Automation;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
#if CORECLR
|
#if CORECLR
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
@ -42,11 +43,28 @@ namespace Microsoft.PowerShell.Commands
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("input");
|
throw new ArgumentNullException("input");
|
||||||
}
|
}
|
||||||
|
|
||||||
error = null;
|
error = null;
|
||||||
#if CORECLR
|
#if CORECLR
|
||||||
object obj = null;
|
object obj = null;
|
||||||
try
|
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 });
|
obj = JsonConvert.DeserializeObject(input, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None, MaxDepth = 1024 });
|
||||||
|
|
||||||
// JObject is a IDictionary
|
// 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
|
# 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) }
|
$versionObject | Add-Member -MemberType ScriptProperty -Name IsOld -Value { ($this.Major -le 3) }
|
||||||
|
|
||||||
$jstr = ConvertTo-Json $versionObject
|
$jstr = ConvertTo-Json $versionObject
|
||||||
|
|
||||||
# convert the JSON string to a JSON object
|
# convert the JSON string to a JSON object
|
||||||
|
@ -1455,4 +1454,25 @@ Describe "Json Bug fixes" -Tags "Feature" {
|
||||||
{
|
{
|
||||||
RunJsonTest $testCase
|
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