using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace RioJoy.Core.Profiles; /// /// Loads and saves as JSON. Replaces the legacy /// SimpleIni single-file config with a profile library (see docs/PLAN.md). /// Newtonsoft rather than System.Text.Json so the net40 (Windows XP) flavor /// shares one serializer โ€” and one on-disk format โ€” with net48 (PLAN.md ยง8A). /// Conventions match the original STJ settings: indented, PascalCase names, /// enums as strings, nulls skipped โ€” existing config.json files parse as-is. /// public static class ConfigStore { private static readonly JsonSerializerSettings Options = new() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore, Converters = { new StringEnumConverter() }, }; public static string Serialize(AppConfig config) { if (config is null) throw new ArgumentNullException(nameof(config)); return JsonConvert.SerializeObject(config, Options); } public static AppConfig Deserialize(string json) { if (string.IsNullOrWhiteSpace(json)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(json)); return JsonConvert.DeserializeObject(json, Options) ?? throw new JsonSerializationException("Config JSON deserialized to null."); } /// Save the config to (creating directories). public static void Save(AppConfig config, string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path)); string? dir = Path.GetDirectoryName(Path.GetFullPath(path)); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); File.WriteAllText(path, Serialize(config)); } /// /// Load the config from , or return a fresh default /// if the file does not exist. /// public static AppConfig Load(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path)); return File.Exists(path) ? Deserialize(File.ReadAllText(path)) : new AppConfig(); } }