From 23e64829bb1f7f088cd0155c092b3cbe0897c5d8 Mon Sep 17 00:00:00 2001 From: Scott Pouliot Date: Tue, 2 Jun 2026 11:06:38 -0400 Subject: [PATCH] Fix formula export/import: embed fields as real JSON array, not escaped string Previously FieldsJson was serialized as an escaped string in the export file, which was fragile and unreadable. Now parsed into a JsonElement and embedded as a proper JSON array under the key "fields". Import reads it back with GetRawText() to reconstruct the stored string. This prevents the null/empty fields bug caused by manually-edited or round-tripped files. Co-Authored-By: Claude Sonnet 4.6 --- .../Controllers/CompanySettingsController.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/PowderCoating.Web/Controllers/CompanySettingsController.cs b/src/PowderCoating.Web/Controllers/CompanySettingsController.cs index bc9ebde..da606eb 100644 --- a/src/PowderCoating.Web/Controllers/CompanySettingsController.cs +++ b/src/PowderCoating.Web/Controllers/CompanySettingsController.cs @@ -3051,6 +3051,15 @@ public class CompanySettingsController : Controller var companyId = _tenantContext.GetCurrentCompanyId()!.Value; var templates = await _unitOfWork.CustomItemTemplates.FindAsync(t => t.CompanyId == companyId); + // Parse FieldsJson into a real JsonElement so it is embedded as a proper JSON array + // in the export file rather than as an escaped string. This makes the file human-readable + // and avoids round-trip corruption when files are manually edited. + static System.Text.Json.JsonElement ParseFields(string? raw) + { + try { return System.Text.Json.JsonDocument.Parse(raw ?? "[]").RootElement.Clone(); } + catch { return System.Text.Json.JsonDocument.Parse("[]").RootElement.Clone(); } + } + var export = new { exportedAt = DateTime.UtcNow, @@ -3062,7 +3071,7 @@ public class CompanySettingsController : Controller t.Name, t.Description, t.OutputMode, - t.FieldsJson, + Fields = ParseFields(t.FieldsJson), t.Formula, t.DefaultRate, t.RateLabel, @@ -3142,7 +3151,8 @@ public class CompanySettingsController : Controller Name = name, Description = item.TryGetProperty("description", out var d) ? d.GetString() : null, OutputMode = item.TryGetProperty("outputMode", out var om) ? om.GetString() ?? "FixedRate" : "FixedRate", - FieldsJson = item.TryGetProperty("fieldsJson", out var fj) ? fj.GetString() ?? "[]" : "[]", + // "fields" is a real JSON array in the export; GetRawText() reconstructs the string + FieldsJson = item.TryGetProperty("fields", out var fj) ? fj.GetRawText() : "[]", Formula = item.TryGetProperty("formula", out var f) ? f.GetString() ?? "" : "", DefaultRate = item.TryGetProperty("defaultRate", out var dr) && dr.ValueKind == System.Text.Json.JsonValueKind.Number ? dr.GetDecimal() : null, RateLabel = item.TryGetProperty("rateLabel", out var rl) ? rl.GetString() : null,