// Return a double representation of JSValue.
        // Boolean is converted to 0.0 or 1.0.
        // Null, Object, and Array are 0.
        public double AsDouble()
        {
            switch (Type)
            {
            case JSValueType.String: return(JSConverter.ToJSNumber(StringValue));

            case JSValueType.Boolean: return(BooleanValue ? 1.0 : 0.0);

            case JSValueType.Int64: return(Int64Value);

            case JSValueType.Double: return(DoubleValue);

            default: return(0);
            }
        }
        // Return an Int64 representation of JSValue.
        // String is converted to double first before converting to Int64.
        // Boolean is converted to 0 or 1.
        // Null, Object, and Array are 0.
        public long AsInt64()
        {
            switch (Type)
            {
            case JSValueType.String: return(JSConverter.ToInt64(JSConverter.ToJSNumber(StringValue)));

            case JSValueType.Boolean: return(BooleanValue ? 1 : 0);

            case JSValueType.Int64: return(Int64Value);

            case JSValueType.Double: return(JSConverter.ToInt64(DoubleValue));

            default: return(0);
            }
        }
        // Return a Double representation of JSValue. It is equivalent to JavaScript Number(value) result.
        public double AsJSNumber()
        {
            switch (Type)
            {
            case JSValueType.Object:
            case JSValueType.Array:
            case JSValueType.String: return(JSConverter.ToJSNumber(AsJSString()));

            case JSValueType.Boolean: return(BooleanValue ? 1 : 0);

            case JSValueType.Int64: return(Int64Value);

            case JSValueType.Double: return(DoubleValue);

            default: return(0);
            }
        }
        // Return a String representation of JSValue.
        // Null is "null".
        // Object and Array are empty strings "".
        // Boolean is "true" or "false".
        // Int64 is converted to string using integer representation.
        // Double uses AsJSString() conversion which uses "NaN", "Infinity", and "-Infinity" for special values.
        public string AsString()
        {
            switch (Type)
            {
            case JSValueType.Null: return(JSConverter.NullString);

            case JSValueType.String: return(StringValue);

            case JSValueType.Boolean: return(JSConverter.ToJSString(BooleanValue));

            case JSValueType.Int64: return(Int64Value.ToString());

            case JSValueType.Double: return(JSConverter.ToJSString(DoubleValue));

            default: return("");
            }
        }
        // Convert JSValue to a readable string that can be used for logging and debugging.
        public override string ToString()
        {
            switch (Type)
            {
            case JSValueType.Null: return(JSConverter.NullString);

            case JSValueType.Object:
            {
                var sb = new StringBuilder();
                sb.Append("{");
                bool start = true;
                foreach (var prop in ObjectValue)
                {
                    if (start)
                    {
                        start = false;
                    }
                    else
                    {
                        sb.Append(", ");
                    }

                    sb.Append(prop.Key);
                    sb.Append(": ");
                    sb.Append(prop.Value.ToString());
                }

                sb.Append("}");
                return(sb.ToString());
            }

            case JSValueType.Array:
            {
                var sb = new StringBuilder();
                sb.Append("[");
                bool start = true;
                foreach (var item in ArrayValue)
                {
                    if (start)
                    {
                        start = false;
                    }
                    else
                    {
                        sb.Append(", ");
                    }

                    sb.Append(item.ToString());
                }

                sb.Append("]");
                return(sb.ToString());
            }

            case JSValueType.String: return("\"" + StringValue + "\"");

            case JSValueType.Boolean: return(JSConverter.ToJSString(BooleanValue));

            case JSValueType.Int64: return(Int64Value.ToString());

            case JSValueType.Double: return(JSConverter.ToJSString(DoubleValue));

            default: return("<Unexpected>");
            }
        }
        // Return a String representation of JSValue. It is equivalent to JavaScript String(value) result.
        public string AsJSString()
        {
            StringBuilder WriteValue(StringBuilder sb, JSValue node)
            {
                switch (node.Type)
                {
                case JSValueType.Null: return(sb.Append(JSConverter.NullString));

                case JSValueType.Object: return(sb.Append(JSConverter.ObjectString));

                case JSValueType.Array:
                {
                    bool start = true;
                    foreach (var item in node.ArrayValue)
                    {
                        if (start)
                        {
                            start = false;
                        }
                        else
                        {
                            sb.Append(',');
                        }

                        WriteValue(sb, item);
                    }
                    return(sb);
                }

                case JSValueType.String: return(sb.Append(node.StringValue));

                case JSValueType.Boolean: return(sb.Append(JSConverter.ToJSString(node.BooleanValue)));

                case JSValueType.Int64: return(sb.Append(node.Int64Value));

                case JSValueType.Double: return(sb.Append(JSConverter.ToJSString(node.DoubleValue)));

                default: return(sb);
                }
            }

            switch (Type)
            {
            case JSValueType.Null: return(JSConverter.NullString);

            case JSValueType.Object: return(JSConverter.ObjectString);

            case JSValueType.Array:
            {
                StringBuilder sb = new StringBuilder();
                WriteValue(sb, this);
                return(sb.ToString());
            }

            case JSValueType.String: return(StringValue);

            case JSValueType.Boolean: return(JSConverter.ToJSString(BooleanValue));

            case JSValueType.Int64: return(Int64Value.ToString());

            case JSValueType.Double: return(JSConverter.ToJSString(DoubleValue));

            default: return("");
            }
        }