Created
January 10, 2023 18:39
-
-
Save tilkinsc/dd9e7f3f1b32a00e831e18189c2e7c3c to your computer and use it in GitHub Desktop.
Effective Json serialization for C# CSharp classes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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