Policy.Autorest/custom/ParameterDefinitionsValue.cs

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.
 
namespace Microsoft.Azure.PowerShell.Cmdlets.Policy.Models
{
    using Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.PowerShell;
    using System;
    using System.Linq;
 
    public partial class ParameterDefinitionsValue
    {
        // Temporary storage used within a single ToJson() call to save scalar DefaultValue and AllowedValue
        // while the generated serialization body runs (which would emit {} for scalar Any entries).
        private Any _savedDefaultValue;
        private System.Collections.Generic.List<Microsoft.Azure.PowerShell.Cmdlets.Policy.Models.IAny> _savedAllowedValue;
 
        /// <summary>
        /// Performs case-insensitive deserialization from a dictionary. This is required because PS7's
        /// <c>ConvertFrom-Json -AsHashtable</c> returns an <c>OrderedDictionary</c> with lowercase keys
        /// matching the JSON, but the generated <c>ParameterDefinitionsValue(IDictionary)</c> constructor
        /// gates each field assignment on <c>content.Contains("PascalCaseName")</c> which is case-sensitive
        /// and therefore misses lowercase keys. <c>GetValueForProperty</c> is already case-insensitive, so
        /// calling it here (without the gate) correctly populates all fields whose key names match.
        /// The <c>allowedValues</c> property is handled separately because its JSON name does not match the
        /// C# property name <c>AllowedValue</c> at all, so even a case-insensitive lookup by property name
        /// would fail to find it.
        /// </summary>
        partial void BeforeDeserializeDictionary(global::System.Collections.IDictionary content, ref bool returnNow)
        {
            // type / Type
            ((IParameterDefinitionsValueInternal)this).Type =
                (string)content.GetValueForProperty("Type", ((IParameterDefinitionsValueInternal)this).Type, global::System.Convert.ToString);
 
            // defaultValue / DefaultValue — AnyTypeConverter.ConvertFrom only handles JSON objects and
            // PS dictionaries; plain scalars (e.g. the string "RequiredTag") fall through and return null.
            // Fall back to Any.FromScalar so scalar defaultValues are preserved.
            ((IParameterDefinitionsValueInternal)this).DefaultValue =
                content.GetValueForProperty("DefaultValue", (IAny)null, (v) =>
                {
                    var converted = AnyTypeConverter.ConvertFrom(v);
                    return converted ?? (v != null ? Any.FromScalar(v) : null);
                });
 
            // schema / Schema
            ((IParameterDefinitionsValueInternal)this).Schema =
                (Microsoft.Azure.PowerShell.Cmdlets.Policy.Models.IAny)content.GetValueForProperty("Schema", ((IParameterDefinitionsValueInternal)this).Schema, Microsoft.Azure.PowerShell.Cmdlets.Policy.Models.AnyTypeConverter.ConvertFrom);
 
            // metadata / Metadata
            ((IParameterDefinitionsValueInternal)this).Metadata =
                (Microsoft.Azure.PowerShell.Cmdlets.Policy.Models.IParameterDefinitionsValueMetadata)content.GetValueForProperty("Metadata", ((IParameterDefinitionsValueInternal)this).Metadata, Microsoft.Azure.PowerShell.Cmdlets.Policy.Models.ParameterDefinitionsValueMetadataTypeConverter.ConvertFrom);
 
            // allowedValues / AllowedValue — JSON name "allowedValues" does not match C# property "AllowedValue",
            // so GetValueForProperty("AllowedValue", ...) cannot find it even case-insensitively.
            var allowedValuesEntry = content.Cast<System.Collections.DictionaryEntry>()
                .FirstOrDefault(e => "allowedValues".Equals(e.Key?.ToString(), StringComparison.OrdinalIgnoreCase));
            if (allowedValuesEntry.Key != null)
            {
                ((IParameterDefinitionsValueInternal)this).AllowedValue =
                    TypeConverterExtensions.SelectToList<Microsoft.Azure.PowerShell.Cmdlets.Policy.Models.IAny>(
                        allowedValuesEntry.Value,
                        v => {
                            var converted = AnyTypeConverter.ConvertFrom(v);
                            return converted ?? (v != null ? Any.FromScalar(v) : null);
                        });
            }
            // Prevent the generated body from running — it re-applies AnyTypeConverter.ConvertFrom
            // to DefaultValue without scalar fallback, overwriting the Any.FromScalar we just set.
            returnNow = true;
        }
 
        partial void AfterDeserializeDictionary(global::System.Collections.IDictionary content)
        {
        }
 
        partial void AfterDeserializePSObject(global::System.Management.Automation.PSObject content)
        {
        }
 
        partial void BeforeDeserializePSObject(global::System.Management.Automation.PSObject content, ref bool returnNow)
        {
        }
 
        /// <summary>
        /// Fixes up deserialization of scalar <c>defaultValue</c> fields from JSON.
        /// The generated constructor uses <c>PropertyT&lt;JsonObject&gt;("defaultValue")</c> which silently
        /// returns null when the value is a JSON string, number, boolean, or array. This hook detects
        /// that case by checking whether <c>_defaultValue</c> is still null while the raw JSON node exists,
        /// and wraps the scalar in an <see cref="Any"/> scalar instance.
        /// Also fixes <c>allowedValues</c> items: <c>Any.FromJson</c> returns null for non-object elements
        /// (e.g., string or number items), so scalar items are replaced with <see cref="Any.FromScalar"/> wrappers.
        /// </summary>
        partial void AfterFromJson(Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.Json.JsonObject json)
        {
            if (json == null) return;
 
            // Fix scalar defaultValue
            if (_defaultValue == null
                && json.TryGetValue("defaultValue", out var rawDefault)
                && rawDefault != null && !rawDefault.IsNull)
            {
                _defaultValue = Any.FromScalar(rawDefault.ToValue());
            }
 
            // Fix scalar items inside allowedValues — Any.FromJson(__u) returns null for non-JsonObject nodes.
            if (_allowedValue != null
                && json.TryGetValue("allowedValues", out var rawAllowed)
                && rawAllowed is Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.Json.XNodeArray xArr)
            {
                for (int i = 0; i < xArr.Count && i < _allowedValue.Count; i++)
                {
                    var node = xArr[i];
                    if (_allowedValue[i] == null && node != null && !node.IsNull)
                    {
                        _allowedValue[i] = Any.FromScalar(node.ToValue());
                    }
                }
            }
        }
 
        /// <summary>
        /// When <c>DefaultValue</c> is a scalar <see cref="Any"/>, the generated serialization body would
        /// call <c>_defaultValue.ToJson()</c> which always produces <c>{}</c> (an empty JSON object).
        /// This hook pre-empts that by writing the correct scalar node into the container directly,
        /// then temporarily nulls <c>_defaultValue</c> so the generated <c>AddIf</c> skips it.
        /// Also handles <c>allowedValues</c> items that are scalar <see cref="Any"/> instances:
        /// the generated foreach calls <c>Any.ToJson()</c> per item which always returns <c>{}</c>
        /// for scalars, so we pre-serialize the whole array and null out <c>_allowedValue</c> temporarily.
        /// <see cref="AfterToJson"/> restores both fields.
        /// </summary>
        partial void BeforeToJson(ref Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.Json.JsonObject container, ref bool returnNow)
        {
            if (_defaultValue is Any anyDV && anyDV.IsScalar)
            {
                var scalarNode = Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.JsonSerializable.ToJsonValue(anyDV.ScalarValue);
                if (scalarNode != null)
                {
                    container.Add("defaultValue", scalarNode);
                }
                // Null out temporarily — the generated AddIf checks `null != this._defaultValue`
                // and will skip the field, leaving the scalar entry we just added intact.
                _savedDefaultValue = anyDV;
                _defaultValue = null;
            }
 
            // If any allowedValues items are scalar-backed Any instances, pre-serialize the whole array.
            if (_allowedValue != null && _allowedValue.Count > 0
                && _allowedValue.Exists(v => v is Any a && a.IsScalar))
            {
                var arr = new Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.Json.XNodeArray();
                foreach (var item in _allowedValue)
                {
                    Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.Json.JsonNode node;
                    if (item is Any a && a.IsScalar)
                    {
                        node = Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.JsonSerializable.ToJsonValue(a.ScalarValue);
                    }
                    else
                    {
                        node = item?.ToJson(null, Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.SerializationMode.None);
                    }
                    if (node != null)
                    {
                        arr.Add(node);
                    }
                }
                container.Add("allowedValues", arr);
                // Null out temporarily so the generated `if (null != this._allowedValue)` block is skipped.
                _savedAllowedValue = _allowedValue;
                _allowedValue = null;
            }
        }
 
        /// <summary>Restores <c>DefaultValue</c> and <c>AllowedValue</c> after the generated serialization body has run.</summary>
        partial void AfterToJson(ref Microsoft.Azure.PowerShell.Cmdlets.Policy.Runtime.Json.JsonObject container)
        {
            if (_savedDefaultValue != null)
            {
                _defaultValue = _savedDefaultValue;
                _savedDefaultValue = null;
            }
            if (_savedAllowedValue != null)
            {
                _allowedValue = _savedAllowedValue;
                _savedAllowedValue = null;
            }
        }
    }
}