ChangeSafety.Autorest/custom/Any.cs

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
 
namespace Microsoft.Azure.PowerShell.Cmdlets.ChangeSafety.Models
{
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Azure.PowerShell.Cmdlets.ChangeSafety.Runtime.Json;
 
    /// <summary>
    /// Partial class to properly handle IAny (free-form object) serialization.
    /// The generated code creates an empty object - this fixes it to store and serialize content.
    /// </summary>
    public partial class Any
    {
        private IDictionary _content;
 
        public IDictionary Content
        {
            get { return _content; }
        }
 
        /// <summary>
        /// Called after deserializing from a dictionary. Stores the content for later serialization.
        /// </summary>
        partial void AfterDeserializeDictionary(IDictionary content)
        {
            _content = content;
        }
 
        /// <summary>
        /// Called after deserializing from a JSON response. Captures the free-form
        /// content so that reading a resource (e.g. ChangeDefinitionDetail) surfaces
        /// the data instead of an empty object. Without this, the generated Any only
        /// hooks the PowerShell-input paths, so values returned by the service are
        /// silently dropped on the read path.
        /// </summary>
        partial void AfterFromJson(Microsoft.Azure.PowerShell.Cmdlets.ChangeSafety.Runtime.Json.JsonObject json)
        {
            if (json != null)
            {
                _content = json.ToValue() as IDictionary;
            }
        }
 
        /// <summary>
        /// Called after deserializing from a PSObject. Converts to dictionary and stores.
        /// </summary>
        partial void AfterDeserializePSObject(System.Management.Automation.PSObject content)
        {
            _content = new Dictionary<string, object>();
            foreach (var prop in content.Properties)
            {
                if (prop.MemberType == System.Management.Automation.PSMemberTypes.NoteProperty)
                {
                    _content[prop.Name] = prop.Value;
                }
            }
        }
 
        /// <summary>
        /// Called before serializing to JSON. Outputs the stored content.
        /// </summary>
        partial void BeforeToJson(ref JsonObject container, ref bool returnNow)
        {
            if (_content != null)
            {
                SerializeDictionary(_content, container);
                returnNow = true;
            }
        }
 
        partial void OverrideToString(ref string stringResult, ref bool returnNow)
        {
            if (_content != null)
            {
                stringResult = FormatValue(_content);
                returnNow = true;
            }
        }
 
        /// <summary>
        /// Recursively serializes a dictionary to a JSON container.
        /// </summary>
        private void SerializeDictionary(IDictionary dict, JsonObject container)
        {
            foreach (DictionaryEntry entry in dict)
            {
                string key = entry.Key?.ToString();
                if (string.IsNullOrEmpty(key)) continue;
 
                container.Add(key, SerializeValue(entry.Value));
            }
        }
 
        /// <summary>
        /// Serializes a value to a JsonNode.
        /// </summary>
        private JsonNode SerializeValue(object value)
        {
            if (value == null)
            {
                return Microsoft.Azure.PowerShell.Cmdlets.ChangeSafety.Runtime.Json.XNull.Instance;
            }
 
            // Handle PSObject wrapper
            if (value is System.Management.Automation.PSObject psObj)
            {
                value = psObj.BaseObject;
            }
 
            // Handle primitives
            if (value is string s)
            {
                return new JsonString(s);
            }
            if (value is bool b)
            {
                return new JsonBoolean(b);
            }
            if (value is int i)
            {
                return new JsonNumber(i);
            }
            if (value is long l)
            {
                return new JsonNumber(l);
            }
            if (value is double d)
            {
                return new JsonNumber(d);
            }
            if (value is float f)
            {
                return new JsonNumber(f);
            }
            if (value is decimal dec)
            {
                return new JsonNumber((double)dec);
            }
 
            // Handle arrays/collections
            if (value is IList list)
            {
                var array = new XNodeArray();
                foreach (var item in list)
                {
                    array.SafeAdd(SerializeValue(item));
                }
                return array;
            }
 
            // Handle object arrays
            if (value is object[] objArray)
            {
                var array = new XNodeArray();
                foreach (var item in objArray)
                {
                    array.SafeAdd(SerializeValue(item));
                }
                return array;
            }
 
            // Handle dictionaries/hashtables
            if (value is IDictionary dict)
            {
                var obj = new JsonObject();
                SerializeDictionary(dict, obj);
                return obj;
            }
 
            // Handle PSObject with properties (like hashtable converted to PSObject)
            if (value is System.Management.Automation.PSObject pso)
            {
                var obj = new JsonObject();
                foreach (var prop in pso.Properties)
                {
                    if (prop.MemberType == System.Management.Automation.PSMemberTypes.NoteProperty)
                    {
                        obj.Add(prop.Name, SerializeValue(prop.Value));
                    }
                }
                return obj;
            }
 
            // Fallback: try to convert to string
            return new JsonString(value.ToString());
        }
 
        private string FormatValue(object value)
        {
            if (value == null)
            {
                return "null";
            }
 
            if (value is System.Management.Automation.PSObject psObj)
            {
                value = psObj.BaseObject;
            }
 
            if (value is string text)
            {
                return "\"" + EscapeString(text) + "\"";
            }
 
            if (value is bool boolean)
            {
                return boolean ? "true" : "false";
            }
 
            if (value is IDictionary dict)
            {
                var builder = new StringBuilder();
                builder.Append("{");
                var isFirst = true;
                foreach (DictionaryEntry entry in dict)
                {
                    if (!isFirst)
                    {
                        builder.Append(",");
                    }
 
                    builder.Append("\"");
                    builder.Append(EscapeString(entry.Key?.ToString() ?? string.Empty));
                    builder.Append("\":");
                    builder.Append(FormatValue(entry.Value));
                    isFirst = false;
                }
 
                builder.Append("}");
                return builder.ToString();
            }
 
            if (value is IList list)
            {
                var builder = new StringBuilder();
                builder.Append("[");
                for (var index = 0; index < list.Count; index++)
                {
                    if (index > 0)
                    {
                        builder.Append(",");
                    }
 
                    builder.Append(FormatValue(list[index]));
                }
 
                builder.Append("]");
                return builder.ToString();
            }
 
            return value.ToString();
        }
 
        private string EscapeString(string value)
        {
            return value
                .Replace("\\", "\\\\")
                .Replace("\"", "\\\"")
                .Replace("\r", "\\r")
                .Replace("\n", "\\n");
        }
    }
}