From 4f866bd75a4507b398572684dd56857a8c3ed270 Mon Sep 17 00:00:00 2001 From: iSazonov Date: Thu, 13 Sep 2018 12:04:26 +0500 Subject: [PATCH 1/5] Add EscapeHandling parameter in ConvertTo-Json cmdlet --- .../utility/WebCmdlet/ConvertToJsonCommand.cs | 24 +++++++++++++++---- .../ConvertTo-Json.Tests.ps1 | 16 +++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs index 1adb1d0d473..7848a61b227 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/ConvertToJsonCommand.cs @@ -2,15 +2,16 @@ // Licensed under the MIT License. using System; -using System.Diagnostics.CodeAnalysis; -using System.Collections.Generic; -using System.Management.Automation; using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Reflection; using System.Text; -using System.Globalization; using Dbg = System.Management.Automation; +using System.Management.Automation; using System.Management.Automation.Internal; + using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -73,6 +74,14 @@ public class ConvertToJsonCommand : PSCmdlet [Parameter] public SwitchParameter AsArray { get; set; } + /// + /// Specifies how strings are escaped when writing JSON text. + /// If the EscapeHandling property is set to EscapeHtml, the result JSON string will + /// be returned with HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. + /// + [Parameter] + public StringEscapeHandling EscapeHandling { get; set; } = StringEscapeHandling.Default; + #endregion parameters #region overrides @@ -125,7 +134,12 @@ protected override void EndProcessing() { return; } - JsonSerializerSettings jsonSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None, MaxDepth = 1024 }; + JsonSerializerSettings jsonSettings = new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.None, + MaxDepth = 1024, + StringEscapeHandling = EscapeHandling + }; if (EnumsAsStrings) { jsonSettings.Converters.Add(new StringEnumConverter()); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 index 5bc819be1c1..423053d80cd 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 @@ -48,4 +48,20 @@ Describe 'ConvertTo-Json' -tags "CI" { $output = 1 | ConvertTo-Json $output | Should -BeExactly '1' } + + It "The result string should be escaped." { + $result1 = @' +{ + "abc": "'def'" +} +'@ + $result2 = @' +{ + "abc": "\u0027def\u0027" +} +'@ + @{ 'abc' = "'def'" } | ConvertTo-Json | Should -BeExactly $result1 + @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling Default | Should -BeExactly $result1 + @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling EscapeHtml | Should -BeExactly $result2 + } } From 9a1feae62ac8d9f4cc328834e8e911310395029a Mon Sep 17 00:00:00 2001 From: iSazonov Date: Thu, 13 Sep 2018 12:58:40 +0500 Subject: [PATCH 2/5] Fix test --- .../ConvertTo-Json.Tests.ps1 | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 index 423053d80cd..49cd742e21a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 @@ -50,18 +50,15 @@ Describe 'ConvertTo-Json' -tags "CI" { } It "The result string should be escaped." { - $result1 = @' -{ - "abc": "'def'" -} -'@ - $result2 = @' -{ - "abc": "\u0027def\u0027" -} -'@ - @{ 'abc' = "'def'" } | ConvertTo-Json | Should -BeExactly $result1 - @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling Default | Should -BeExactly $result1 - @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling EscapeHtml | Should -BeExactly $result2 + if ($isWindows) { + $newline = "`r`n" + } else { + $newline = "`n" + } + $expected1 = "{$newline ""abc"": ""'def'""$newline}" + $expected2 = "{$newline ""abc"": ""\u0027def\u0027""$newline}" + @{ 'abc' = "'def'" } | ConvertTo-Json | Should -BeExactly $expected1 + @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling Default | Should -BeExactly $expected1 + @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling EscapeHtml | Should -BeExactly $expected2 } } From 488fd3c7c9aa8f424999f0ddd86850d9614c9efd Mon Sep 17 00:00:00 2001 From: iSazonov Date: Mon, 17 Sep 2018 12:41:24 +0500 Subject: [PATCH 3/5] Split tests --- .../ConvertTo-Json.Tests.ps1 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 index 49cd742e21a..91362e4c0e9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 @@ -49,16 +49,18 @@ Describe 'ConvertTo-Json' -tags "CI" { $output | Should -BeExactly '1' } - It "The result string should be escaped." { - if ($isWindows) { - $newline = "`r`n" - } else { - $newline = "`n" - } + It "The result string should be not escaped by default." { + $newline = [System.Environment]::NewLine $expected1 = "{$newline ""abc"": ""'def'""$newline}" - $expected2 = "{$newline ""abc"": ""\u0027def\u0027""$newline}" + @{ 'abc' = "'def'" } | ConvertTo-Json | Should -BeExactly $expected1 @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling Default | Should -BeExactly $expected1 + } + + It "The result string should be escaped with '-EscapeHandling EscapeHtml'." { + $newline = [System.Environment]::NewLine + $expected2 = "{$newline ""abc"": ""\u0027def\u0027""$newline}" + @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling EscapeHtml | Should -BeExactly $expected2 } } From 7ef9f1022f0fb24c8dd384898ea8430d08f08f25 Mon Sep 17 00:00:00 2001 From: iSazonov Date: Mon, 17 Sep 2018 14:52:38 +0500 Subject: [PATCH 4/5] Fix bug in test and use TestCases --- .../ConvertTo-Json.Tests.ps1 | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 index 91362e4c0e9..ff4e63ef26a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 @@ -1,6 +1,10 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. Describe 'ConvertTo-Json' -tags "CI" { + BeforeAll { + $newline = [System.Environment]::NewLine + } + It 'Newtonsoft.Json.Linq.Jproperty should be converted to Json properly' { $EgJObject = New-Object -TypeName Newtonsoft.Json.Linq.JObject $EgJObject.Add("TestValue1", "123456") @@ -22,7 +26,7 @@ Describe 'ConvertTo-Json' -tags "CI" { $null = $ps.AddScript({ $obj = [PSCustomObject]@{P1 = ''; P2 = ''; P3 = ''; P4 = ''; P5 = ''; P6 = ''} $obj.P1 = $obj.P2 = $obj.P3 = $obj.P4 = $obj.P5 = $obj.P6 = $obj - 1..100 | Foreach-Object { $obj } | ConvertTo-Json -Depth 10 -Verbose + 1..100 | Foreach-Object { $obj } | ConvertTo-Json -Depth 10 # the conversion is expected to take some time, this throw is in case it doesn't throw "Should not have thrown exception" }) @@ -49,18 +53,13 @@ Describe 'ConvertTo-Json' -tags "CI" { $output | Should -BeExactly '1' } - It "The result string should be not escaped by default." { - $newline = [System.Environment]::NewLine - $expected1 = "{$newline ""abc"": ""'def'""$newline}" - - @{ 'abc' = "'def'" } | ConvertTo-Json | Should -BeExactly $expected1 - @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling Default | Should -BeExactly $expected1 - } - - It "The result string should be escaped with '-EscapeHandling EscapeHtml'." { - $newline = [System.Environment]::NewLine - $expected2 = "{$newline ""abc"": ""\u0027def\u0027""$newline}" + It "The result string should ." -TestCases @( + @{name = "be not escaped by default."; params = @{}; expected = "{$newline ""abc"": ""'def'""$newline}" } + @{name = "be not escaped with '-EscapeHandling Default'."; params = @{EscapeHandling = 'Default'}; expected = "{$newline ""abc"": ""'def'""$newline}" } + @{name = "be escaped with '-EscapeHandling EscapeHtml'."; params = @{EscapeHandling = 'EscapeHtml'}; expected = "{$newline ""abc"": ""\u0027def\u0027""$newline}" } + ) { + param ($name, $params ,$expected) - @{ 'abc' = "'def'" } | ConvertTo-Json -EscapeHandling EscapeHtml | Should -BeExactly $expected2 + @{ 'abc' = "'def'" } | ConvertTo-Json @params | Should -BeExactly $expected } } From 0a6516aa84640425641f261463ad074335f1223f Mon Sep 17 00:00:00 2001 From: iSazonov Date: Tue, 25 Sep 2018 10:32:18 +0500 Subject: [PATCH 5/5] Revert test change --- .../Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 index ff4e63ef26a..198cccf5964 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 @@ -26,7 +26,7 @@ Describe 'ConvertTo-Json' -tags "CI" { $null = $ps.AddScript({ $obj = [PSCustomObject]@{P1 = ''; P2 = ''; P3 = ''; P4 = ''; P5 = ''; P6 = ''} $obj.P1 = $obj.P2 = $obj.P3 = $obj.P4 = $obj.P5 = $obj.P6 = $obj - 1..100 | Foreach-Object { $obj } | ConvertTo-Json -Depth 10 + 1..100 | Foreach-Object { $obj } | ConvertTo-Json -Depth 10 -Verbose # the conversion is expected to take some time, this throw is in case it doesn't throw "Should not have thrown exception" })