// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Text.Json; using System.Text.Json.Nodes; namespace Microsoft.CommandPalette.Extensions.Toolkit; public abstract class JsonSettingsManager { public Settings Settings { get; } = new(); public string FilePath { get; init; } = string.Empty; private static readonly JsonSerializerOptions _serializerOptions = new() { WriteIndented = true, }; public virtual void LoadSettings() { if (string.IsNullOrEmpty(FilePath)) { throw new InvalidOperationException($"You must set a valid {nameof(FilePath)} before calling {nameof(LoadSettings)}"); } var filePath = FilePath; if (!File.Exists(filePath)) { ExtensionHost.LogMessage(new LogMessage() { Message = "The provided settings file does not exist" }); return; } try { // Read the JSON content from the file var jsonContent = File.ReadAllText(filePath); // Is it valid JSON? if (JsonNode.Parse(jsonContent) is JsonObject savedSettings) { Settings.Update(jsonContent); } else { ExtensionHost.LogMessage(new LogMessage() { Message = "Failed to parse settings file as JsonObject." }); } } catch (Exception ex) { ExtensionHost.LogMessage(new LogMessage() { Message = ex.ToString() }); } } public virtual void SaveSettings() { if (string.IsNullOrEmpty(FilePath)) { throw new InvalidOperationException($"You must set a valid {nameof(FilePath)} before calling {nameof(SaveSettings)}"); } try { // Serialize the main dictionary to JSON and save it to the file var settingsJson = Settings.ToJson(); // Is it valid JSON? if (JsonNode.Parse(settingsJson) is JsonObject newSettings) { // Now, read the existing content from the file var oldContent = File.Exists(FilePath) ? File.ReadAllText(FilePath) : "{}"; // Is it valid JSON? if (JsonNode.Parse(oldContent) is JsonObject savedSettings) { foreach (var item in newSettings) { savedSettings[item.Key] = item.Value is not null ? item.Value.DeepClone() : null; } var serialized = savedSettings.ToJsonString(_serializerOptions); File.WriteAllText(FilePath, serialized); } else { ExtensionHost.LogMessage(new LogMessage() { Message = "Failed to parse settings file as JsonObject." }); } } else { ExtensionHost.LogMessage(new LogMessage() { Message = "Failed to parse settings file as JsonObject." }); } } catch (Exception ex) { ExtensionHost.LogMessage(new LogMessage() { Message = ex.ToString() }); } } }