using System.Text; using NpgsqlTypes; namespace NpgsqlRest; /// /// Shared JSON value formatting for column values. /// Used by both single-command and multi-command rendering paths /// to guarantee identical output for the same column types. /// internal static class JsonValueFormatter { /// /// Format a single column value into the output buffer as JSON. /// Handles: null, arrays, array-of-composites, numeric, boolean, JSON, datetime, text with escaping. /// /// Raw string value from PostgreSQL (via AllResultTypesAreUnknown) /// The original object value (for DBNull check) /// Type descriptor for this column /// StringBuilder to write formatted value to /// Array composite dictionary from Routine, or null /// Column index for array composite lookup [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static void FormatValue( ReadOnlySpan raw, object value, TypeDescriptor descriptor, StringBuilder outputBuffer, Dictionary? routineArrayCompositeInfo, int columnIndex) { if (value == DBNull.Value) { outputBuffer.Append(Consts.Null); return; } if (descriptor.IsArray) { // Check if this is an array of composite types if (routineArrayCompositeInfo is not null && routineArrayCompositeInfo.TryGetValue(columnIndex, out var arrayCompositeInfo)) { outputBuffer.Append(PgCompositeArrayToJsonArray(raw, arrayCompositeInfo.FieldNames, arrayCompositeInfo.FieldDescriptors)); } else { outputBuffer.Append(PgArrayToJsonArray(raw, descriptor)); } return; } if ((descriptor.Category & (TypeCategory.Numeric | TypeCategory.Boolean | TypeCategory.Json)) != 0) { if ((descriptor.Category & TypeCategory.Boolean) != 0) { if (raw.Length == 1 && raw[0] == 't') { outputBuffer.Append(Consts.True); } else if (raw.Length == 1 && raw[0] == 'f') { outputBuffer.Append(Consts.False); } else { outputBuffer.Append(raw); } } else { // numeric and json passthrough outputBuffer.Append(raw); } return; } // Text and other types if (descriptor.ActualDbType == NpgsqlDbType.Unknown) { outputBuffer.Append(PgUnknownToJsonArray(ref raw)); } else if (descriptor.NeedsEscape) { outputBuffer.Append(SerializeString(ref raw)); } else if ((descriptor.Category & TypeCategory.DateTime) != 0) { outputBuffer.Append(QuoteDateTime(ref raw)); } else { outputBuffer.Append(Quote(ref raw)); } } }