using System; using System.Collections.Generic; using System.IO; using Microsoft.Xna.Framework.Input; using Newtonsoft.Json; using StardewModdingAPI.Advanced; namespace StardewModdingAPI.Framework.Serialisation { /// Encapsulates SMAPI's JSON file parsing. internal class JsonHelper { /********* ** Accessors *********/ /// The JSON settings to use when serialising and deserialising files. private readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { Formatting = Formatting.Indented, ObjectCreationHandling = ObjectCreationHandling.Replace, // avoid issue where default ICollection values are duplicated each time the config is loaded Converters = new List { new SelectiveStringEnumConverter(typeof(Buttons), typeof(Keys)) } }; /********* ** Public methods *********/ /// Read a JSON file. /// The model type. /// The absolete file path. /// The mod helper to inject for instances. /// Returns the deserialised model, or null if the file doesn't exist or is empty. public TModel ReadJsonFile(string fullPath, IModHelper modHelper) where TModel : class { // read file string json; try { json = File.ReadAllText(fullPath); } catch (Exception ex) when (ex is DirectoryNotFoundException || ex is FileNotFoundException) { return null; } // deserialise model TModel model = JsonConvert.DeserializeObject(json, this.JsonSettings); if (model is IConfigFile) { var wrapper = (IConfigFile)model; wrapper.ModHelper = modHelper; wrapper.FilePath = fullPath; } return model; } /// Save to a JSON file. /// The model type. /// The absolete file path. /// The model to save. public void WriteJsonFile(string fullPath, TModel model) where TModel : class { // create directory if needed string dir = Path.GetDirectoryName(fullPath); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); // write file string json = JsonConvert.SerializeObject(model, this.JsonSettings); File.WriteAllText(fullPath, json); } } }