ConvertFrom-Json: Add -DateKind parameter (#20925)

Adds the -DateKind parameter to the ConvertFrom-Json that allows the
caller to control how DateTime strings are converted into an object. The
default behaviour is to create a DateTime value with the Kind being
Unspecified if no TZ is set, Utc if the TZ Z is set, Local (after
conversion) if an explicit TZ is set. This adds a Utc, Local to
explicitly set the Kind as desired as well as a Offset and String value
to create a DateTimeOffset or keep as a string.
This commit is contained in:
Jordan Borean
2024-02-13 09:05:07 +05:00
committed by GitHub
parent 0393ef261a
commit 71035543e7
4 changed files with 288 additions and 3 deletions
@@ -49,6 +49,12 @@ namespace Microsoft.PowerShell.Commands
[Parameter]
public SwitchParameter NoEnumerate { get; set; }
/// <summary>
/// Gets or sets the switch to control how DateTime values are to be parsed as a dotnet object.
/// </summary>
[Parameter]
public JsonDateKind DateKind { get; set; } = JsonDateKind.Default;
#endregion parameters
#region overrides
@@ -113,7 +119,7 @@ namespace Microsoft.PowerShell.Commands
private bool ConvertFromJsonHelper(string input)
{
ErrorRecord error = null;
object result = JsonObject.ConvertFromJson(input, AsHashtable.IsPresent, Depth, out error);
object result = JsonObject.ConvertFromJson(input, AsHashtable.IsPresent, Depth, DateKind, out error);
if (error != null)
{
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#nullable enable
namespace Microsoft.PowerShell.Commands
{
/// <summary>
/// Enums for ConvertFrom-Json -DateKind parameter.
/// </summary>
public enum JsonDateKind
{
/// <summary>
/// DateTime values are returned as a DateTime with the Kind representing the time zone in the raw string.
/// </summary>
Default,
/// <summary>
/// DateTime values are returned as the Local kind representation of the value.
/// </summary>
Local,
/// <summary>
/// DateTime values are returned as the UTC kind representation of the value.
/// </summary>
Utc,
/// <summary>
/// DateTime values are returned as a DateTimeOffset value preserving the timezone information.
/// </summary>
Offset,
/// <summary>
/// DateTime values are returned as raw strings.
/// </summary>
String,
}
}
@@ -151,9 +151,58 @@ namespace Microsoft.PowerShell.Commands
/// if the <paramref name="returnHashtable"/> parameter is true.</returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Preferring Json over JSON")]
public static object ConvertFromJson(string input, bool returnHashtable, int? maxDepth, out ErrorRecord error)
=> ConvertFromJson(input, returnHashtable, maxDepth, jsonDateKind: JsonDateKind.Default, out error);
/// <summary>
/// Convert a JSON string back to an object of type <see cref="System.Management.Automation.PSObject"/> or
/// <see cref="System.Collections.Hashtable"/> depending on parameter <paramref name="returnHashtable"/>.
/// </summary>
/// <param name="input">The JSON text to convert.</param>
/// <param name="returnHashtable">True if the result should be returned as a <see cref="System.Collections.Hashtable"/>
/// instead of a <see cref="System.Management.Automation.PSObject"/>.</param>
/// <param name="maxDepth">The max depth allowed when deserializing the json input. Set to null for no maximum.</param>
/// <param name="jsonDateKind">Controls how DateTime values are to be converted.</param>
/// <param name="error">An error record if the conversion failed.</param>
/// <returns>A <see cref="System.Management.Automation.PSObject"/> or a <see cref="System.Collections.Hashtable"/>
/// if the <paramref name="returnHashtable"/> parameter is true.</returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Justification = "Preferring Json over JSON")]
internal static object ConvertFromJson(string input, bool returnHashtable, int? maxDepth, JsonDateKind jsonDateKind, out ErrorRecord error)
{
ArgumentNullException.ThrowIfNull(input);
DateParseHandling dateParseHandling;
DateTimeZoneHandling dateTimeZoneHandling;
switch (jsonDateKind)
{
case JsonDateKind.Default:
dateParseHandling = DateParseHandling.DateTime;
dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
break;
case JsonDateKind.Local:
dateParseHandling = DateParseHandling.DateTime;
dateTimeZoneHandling = DateTimeZoneHandling.Local;
break;
case JsonDateKind.Utc:
dateParseHandling = DateParseHandling.DateTime;
dateTimeZoneHandling = DateTimeZoneHandling.Utc;
break;
case JsonDateKind.Offset:
dateParseHandling = DateParseHandling.DateTimeOffset;
dateTimeZoneHandling = DateTimeZoneHandling.Unspecified;
break;
case JsonDateKind.String:
dateParseHandling = DateParseHandling.None;
dateTimeZoneHandling = DateTimeZoneHandling.Unspecified;
break;
default:
throw new ArgumentException($"Unknown JsonDateKind value requested '{jsonDateKind}'");
}
error = null;
try
{
@@ -161,6 +210,9 @@ namespace Microsoft.PowerShell.Commands
input,
new JsonSerializerSettings
{
DateParseHandling = dateParseHandling,
DateTimeZoneHandling = dateTimeZoneHandling,
// This TypeNameHandling setting is required to be secure.
TypeNameHandling = TypeNameHandling.None,
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,