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;
}
}