Skip to content

Instantly share code, notes, and snippets.

@tilkinsc
Created January 10, 2023 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tilkinsc/dd9e7f3f1b32a00e831e18189c2e7c3c to your computer and use it in GitHub Desktop.
Save tilkinsc/dd9e7f3f1b32a00e831e18189c2e7c3c to your computer and use it in GitHub Desktop.
Effective Json serialization for C# CSharp classes
using System.Text.Json;
namespace Meerkat.Json;
public interface IJSONSerializable
{
}
/// <summary>
/// Implements the ability to load JSON files. By default, if the json file
/// falls out of scope it will be saved. Guaranteed to always return default
/// values specified by the implementing class' constructor.
/// </summary>
/// <typeparam name="T">
/// A JSON data class which implements IJSONSerializable and implements a default constructor.
/// </typeparam>
public sealed class JSONSerializable<T> : IDisposable where T : class, IJSONSerializable, new()
{
public string Path { get; private set; }
public T Data { get; private set; }
public bool ShouldSaveAutomatically { get; set; }
private JSONSerializable(T data, string path, bool shouldSaveAutomatically)
{
Path = path;
Data = data;
ShouldSaveAutomatically = shouldSaveAutomatically;
}
public void Save()
{
try
{
JsonSerializerOptions jso = new JsonSerializerOptions { WriteIndented = true, IncludeFields = true };
byte[] json = JsonSerializer.SerializeToUtf8Bytes<T>(Data, jso);
if (!File.Exists(Path))
File.Create(Path);
File.WriteAllBytes(Path, json);
}
catch
{
Console.Error.WriteLine($"'{typeof(T).FullName}' saving JSON failed on file '{Path}'");
throw;
}
}
public void Reload(bool throwOnFailure = true)
{
using (StreamReader sr = new StreamReader(Path))
{
string json = sr.ReadToEnd();
T? obj = JsonSerializer.Deserialize<T>(json) ?? new T();
if (throwOnFailure && obj == null)
throw new ArgumentException($"'{typeof(T).FullName}' loading JSON failed on file '{Path}'");
}
}
public void Dispose()
{
if (ShouldSaveAutomatically)
{
Save();
}
}
public static JSONSerializable<T> Load(string path, bool throwOnFailure = false, bool shouldSaveAutomatically = true)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException("[string path] must not be null or empty.");
try
{
using (StreamReader sr = new StreamReader(path))
{
string json = sr.ReadToEnd();
T? obj = JsonSerializer.Deserialize<T>(json);
return new JSONSerializable<T>(obj ?? new T(), path, shouldSaveAutomatically);
}
}
catch
{
Console.Error.WriteLine($"'{typeof(T).FullName}' loading JSON failed on file '{path}'");
throw;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment