using System.Text.Json; namespace WordVersioning.Api.Services; /// แปลง/ตรวจ map ของ fields (JSON object รูป { tag: value }) ที่ client ส่งมา — /// ใช้ทั้ง form field `fields` ของ upload (FR-11) และ body `values` ของ generate (FR-10) public static class FieldMapJson { /// parse จาก string — คืน false พร้อมข้อความ error เมื่อ JSON ไม่ถูกต้อง public static bool TryParse(string? json, out Dictionary map, out string? error) { map = []; error = null; if (string.IsNullOrWhiteSpace(json)) return true; try { using var doc = JsonDocument.Parse(json); return TryNormalize(doc.RootElement, out map, out error); } catch (JsonException) { error = "`fields` ไม่ใช่ JSON ที่ถูกต้อง"; return false; } } /// normalize จาก JsonElement — ค่า scalar (string/number/bool/null) เท่านั้น /// null กลายเป็น null ใน map (จะถูกมองเป็นค่าว่าง ไม่ใช่ field หาย) public static bool TryNormalize(JsonElement element, out Dictionary map, out string? error) { map = []; error = null; if (element.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined) return true; if (element.ValueKind != JsonValueKind.Object) { error = "ต้องเป็น JSON object รูป { tag: value }"; return false; } foreach (var prop in element.EnumerateObject()) { string? value = prop.Value.ValueKind switch { JsonValueKind.String => prop.Value.GetString(), JsonValueKind.Number => prop.Value.GetRawText(), JsonValueKind.True => "true", JsonValueKind.False => "false", JsonValueKind.Null => null, _ => null, }; if (prop.Value.ValueKind is not (JsonValueKind.String or JsonValueKind.Number or JsonValueKind.True or JsonValueKind.False or JsonValueKind.Null)) { error = $"ค่าของ `{prop.Name}` ต้องเป็น scalar (string/number/bool/null)"; return false; } map[prop.Name] = value; } return true; } }