Cleanup Json cmdlets (#5001)

This commit is contained in:
Ilya
2017-10-06 09:03:53 -07:00
committed by Dongbo Wang
parent c83cf72dbf
commit 50f6667bdb
5 changed files with 2 additions and 241 deletions
@@ -35,29 +35,6 @@ namespace Microsoft.PowerShell.Commands
#region overrides
/// <summary>
/// Prerequisite checks
/// </summary>
protected override void BeginProcessing()
{
#if CORECLR
JsonObject.ImportJsonDotNetModule(this);
#else
try
{
System.Reflection.Assembly.Load(new AssemblyName("System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"));
}
catch (System.IO.FileNotFoundException)
{
ThrowTerminatingError(new ErrorRecord(
new NotSupportedException(WebCmdletStrings.ExtendedProfileRequired),
"ExtendedProfileRequired",
ErrorCategory.NotInstalled,
null));
}
#endif
}
/// <summary>
/// Buffers InputObjet contents available in the pipeline.
/// </summary>
@@ -12,13 +12,8 @@ using System.Text;
using System.Globalization;
using Dbg = System.Management.Automation;
using System.Management.Automation.Internal;
#if CORECLR
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
#else
using System.Collections.Specialized;
using System.Web.Script.Serialization;
#endif
// FxCop suppressions for resource strings:
[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "WebCmdletStrings.resources", MessageId = "json")]
@@ -88,22 +83,6 @@ namespace Microsoft.PowerShell.Commands
ErrorCategory.InvalidOperation,
null));
}
#if CORECLR
JsonObject.ImportJsonDotNetModule(this);
#else
try
{
System.Reflection.Assembly.Load(new AssemblyName("System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"));
}
catch (System.IO.FileNotFoundException)
{
ThrowTerminatingError(new ErrorRecord(
new NotSupportedException(WebCmdletStrings.ExtendedProfileRequired),
"ExtendedProfileRequired",
ErrorCategory.NotInstalled,
null));
}
#endif
}
private List<object> _inputObjects = new List<object>();
@@ -130,7 +109,6 @@ namespace Microsoft.PowerShell.Commands
// Pre-process the object so that it serializes the same, except that properties whose
// values cannot be evaluated are treated as having the value null.
object preprocessedObject = ProcessValue(objectToProcess, 0);
#if CORECLR
JsonSerializerSettings jsonSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None, MaxDepth = 1024 };
if (EnumsAsStrings)
{
@@ -142,17 +120,6 @@ namespace Microsoft.PowerShell.Commands
}
string output = JsonConvert.SerializeObject(preprocessedObject, jsonSettings);
WriteObject(output);
#else
// In Full CLR, we use the JavaScriptSerializer for which RecursionLimit was set to the default value of 100 (the actual recursion limit is 99 since
// at 100 the exception is thrown). See https://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.recursionlimit(v=vs.110).aspx
// ProcessValue creates an object to be serialized from 1 to depth. However, the properties of the object at 'depth' should also be serialized,
// and from the perspective of the serializer, this means it needs to support serializing depth + 1. For the JavaScriptSerializer to support this,
// RecursionLimit needs to be set to depth + 2.
JavaScriptSerializer helper = new JavaScriptSerializer() { RecursionLimit = (maxDepthAllowed + 2) };
helper.MaxJsonLength = Int32.MaxValue;
string output = helper.Serialize(preprocessedObject);
WriteObject(Compress ? output : ConvertToPrettyJsonString(output));
#endif
}
}
@@ -517,11 +484,7 @@ namespace Microsoft.PowerShell.Commands
}
else
{
#if CORECLR
rv = ProcessCustomObject<JsonIgnoreAttribute>(obj, depth);
#else
rv = ProcessCustomObject<ScriptIgnoreAttribute>(obj, depth);
#endif
isCustomObj = true;
}
}
@@ -69,8 +69,6 @@ namespace Microsoft.PowerShell.Commands
);
bool convertSuccess = false;
// On CoreCLR, we need to explicitly load Json.NET
JsonObject.ImportJsonDotNetModule(this);
if (returnType == RestReturnType.Json)
{
convertSuccess = TryConvertToJson(str, out obj, ref ex) || TryConvertToXml(str, out obj, ref ex);
@@ -8,17 +8,12 @@ using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Management.Automation;
using System.Text.RegularExpressions;
#if CORECLR
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation.Internal;
using System.Reflection;
#else
using System.Web.Script.Serialization;
using System.Collections.Specialized;
#endif
namespace Microsoft.PowerShell.Commands
{
@@ -45,7 +40,6 @@ namespace Microsoft.PowerShell.Commands
}
error = null;
#if CORECLR
object obj = null;
try
{
@@ -89,28 +83,9 @@ namespace Microsoft.PowerShell.Commands
// 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.
// Setting RecursionLimit to depth + 2 in order to support '$object | ConvertTo-Json –depth <value less than or equal to 100> | ConvertFrom-Json'.
JavaScriptSerializer serializer = new JavaScriptSerializer(new JsonObjectTypeResolver()) { RecursionLimit = (maxDepthAllowed + 2) };
serializer.MaxJsonLength = Int32.MaxValue;
object obj = serializer.DeserializeObject(input);
if (obj is IDictionary<string, object>)
{
var dictionary = obj as IDictionary<string, object>;
obj = PopulateFromDictionary(dictionary, out error);
}
else if (obj is ICollection<object>)
{
var list = obj as ICollection<object>;
obj = PopulateFromList(list, out error);
}
#endif
return obj;
}
#if CORECLR
// This function is a clone of PopulateFromDictionary using JObject as an input.
private static PSObject PopulateFromJDictionary(JObject entries, out ErrorRecord error)
{
@@ -205,157 +180,5 @@ namespace Microsoft.PowerShell.Commands
}
return result.ToArray();
}
/// <summary>
/// Loads the Json.Net module to the given cmdlet execution context.
/// </summary>
/// <param name="cmdlet"></param>
/// <returns></returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public static void ImportJsonDotNetModule(Cmdlet cmdlet)
{
const string jsonDotNetAssemblyName = "Newtonsoft.Json, Version=7.0.0.0";
// Check if the Newtonsoft.Json.dll assembly is loaded.
try
{
System.Reflection.Assembly.Load(new AssemblyName(jsonDotNetAssemblyName));
}
catch (System.IO.FileNotFoundException)
{
// It is not, try to load it.
// Make sure that PSModuleAutoLoadingPreference is not set to 'None'.
PSModuleAutoLoadingPreference moduleAutoLoadingPreference =
CommandDiscovery.GetCommandDiscoveryPreference(cmdlet.Context, SpecialVariables.PSModuleAutoLoadingPreferenceVarPath, "PSModuleAutoLoadingPreference");
if (moduleAutoLoadingPreference == PSModuleAutoLoadingPreference.None)
{
cmdlet.ThrowTerminatingError(new ErrorRecord(
new NotSupportedException(WebCmdletStrings.PSModuleAutoloadingPreferenceNotEnable),
"PSModuleAutoloadingPreferenceNotEnable",
ErrorCategory.NotEnabled,
null));
}
// Use module auto-loading to import Json.Net.
var jsonNetModulePath = Path.Combine(System.Environment.GetEnvironmentVariable("ProgramFiles"), @"WindowsPowerShell\Modules\Json.Net");
CmdletInfo cmdletInfo = cmdlet.Context.SessionState.InvokeCommand.GetCmdlet("Microsoft.PowerShell.Core\\Import-Module");
Exception exception;
Collection<PSModuleInfo> importedModule = CommandDiscovery.AutoloadSpecifiedModule(jsonNetModulePath, cmdlet.Context, cmdletInfo.Visibility, out exception);
if ((importedModule == null) || (importedModule.Count == 0))
{
string errorMessage = StringUtil.Format(WebCmdletStrings.JsonNetModuleRequired, WebCmdletStrings.CouldNotAutoImportJsonNetModule);
cmdlet.ThrowTerminatingError(new ErrorRecord(
new NotSupportedException(errorMessage, exception),
"CouldNotAutoImportJsonNetModule",
ErrorCategory.InvalidOperation,
null));
}
// Finally, ensure that the Newtonsoft.Json.dll assembly was loaded.
try
{
System.Reflection.Assembly.Load(new AssemblyName(jsonDotNetAssemblyName));
}
catch (System.IO.FileNotFoundException)
{
string errorMessage = StringUtil.Format(
WebCmdletStrings.JsonNetModuleRequired,
StringUtil.Format(WebCmdletStrings.JsonNetModuleFilesRequired, jsonNetModulePath));
cmdlet.ThrowTerminatingError(new ErrorRecord(
new NotSupportedException(errorMessage),
"JsonNetModuleRequired",
ErrorCategory.NotInstalled,
null));
}
}
}
#else
private static ICollection<object> PopulateFromList(ICollection<object> list, out ErrorRecord error)
{
error = null;
List<object> result = new List<object>();
foreach (object element in list)
{
if (element is IDictionary<string, object>)
{
IDictionary<string, object> dic = element as IDictionary<string, object>;
PSObject dicResult = PopulateFromDictionary(dic, out error);
if (error != null)
{
return null;
}
result.Add(dicResult);
}
else if (element is ICollection<object>)
{
ICollection<object> subList = element as ICollection<object>;
ICollection<object> listResult = PopulateFromList(subList, out error);
if (error != null)
{
return null;
}
result.Add(listResult);
}
else
{
result.Add(element);
}
}
return result.ToArray();
}
private static PSObject PopulateFromDictionary(IDictionary<string, object> entries, out ErrorRecord error)
{
error = null;
PSObject result = new PSObject();
foreach (KeyValuePair<string, object> entry in entries)
{
PSPropertyInfo property = result.Properties[entry.Key];
if (property != null)
{
string errorMsg = string.Format(CultureInfo.InvariantCulture,
WebCmdletStrings.DuplicateKeysInJsonString, property.Name, entry.Key);
error = new ErrorRecord(
new InvalidOperationException(errorMsg),
"DuplicateKeysInJsonString",
ErrorCategory.InvalidOperation,
null);
return null;
}
if (entry.Value is IDictionary<string, object>)
{
IDictionary<string, object> subEntries = entry.Value as IDictionary<string, object>;
PSObject dicResult = PopulateFromDictionary(subEntries, out error);
if (error != null)
{
return null;
}
result.Properties.Add(new PSNoteProperty(entry.Key, dicResult));
}
else if (entry.Value is ICollection<object>)
{
ICollection<object> list = entry.Value as ICollection<object>;
ICollection<object> listResult = PopulateFromList(list, out error);
if (error != null)
{
return null;
}
result.Properties.Add(new PSNoteProperty(entry.Key, listResult));
}
else
{
result.Properties.Add(new PSNoteProperty(entry.Key, entry.Value));
}
}
return result;
}
#endif
}
}
}
@@ -9,7 +9,7 @@
<ItemGroup>
<ProjectReference Include="..\Microsoft.PowerShell.CoreCLR.Eventing\Microsoft.PowerShell.CoreCLR.Eventing.csproj" />
<PackageReference Include="Microsoft.Win32.Registry.AccessControl" Version="4.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.4.0" />
<PackageReference Include="System.Security.AccessControl" Version="4.4.0" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.4.0" />