using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace GB5Shared.UnixEpochDate { public sealed class UnixEpochDateTimeConverter : JsonConverter { private static readonly DateTime Epoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => Epoch.AddSeconds(reader.GetInt64()); public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { var seconds = (long)(value.ToUniversalTime() - Epoch).TotalSeconds; writer.WriteNumberValue(seconds); } } public static class JsonOptionsFactory { // ✅ Default (ISO 8601) public static readonly JsonSerializerOptions IsoOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = false }; // ✅ Legacy (Unix Epoch) public static readonly JsonSerializerOptions EpochOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = false, Converters = { new UnixEpochDateTimeConverter() } }; } public sealed class EpochAwareResponseSerializer : IResponseSerializer { public async Task SerializeAsync( HttpContext context, object? response, CancellationToken cancellationToken) { // Nothing to serialize if (response is null) return; // Read header: epochformat (0 = epoch, 1 = iso) var epochHeader = context.Request.Headers["epochformat"].ToString(); bool useEpoch = epochHeader == "0"; var options = useEpoch ? JsonOptionsFactory.EpochOptions : JsonOptionsFactory.IsoOptions; context.Response.ContentType = "application/json"; await JsonSerializer.SerializeAsync( context.Response.Body, response, response.GetType(), options, cancellationToken); } } }