C# JsonConfig
本文最后更新于 205 天前,其中的信息可能已经有所发展或是发生改变。
依赖 System.Text.Json
using System.IO;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;

/// <summary>
/// 提供使用 JSON 快速加载和保存配置的功能。
/// </summary>
public abstract class JsonConfig
{
    /// <summary>
    /// 配置路径。
    /// </summary>
    [JsonIgnore]
    public string Path { get; set; }

    /// <summary>
    /// 默认配置路径。
    /// </summary>
    protected virtual string DefaultPath => $"{GetType().Name}.json";

    /// <summary>
    /// 配置选项。
    /// </summary>
    [JsonIgnore]
    public JsonConfigOptions Options { get; set; }

    /// <summary>
    /// 默认配置选项。
    /// </summary>
    protected virtual JsonConfigOptions DefaultOptions => null;

    /// <summary>
    /// 全局配置选项。
    /// </summary>
    public static JsonConfigOptions GlobalOptions { get; set; } = new();

    /// <summary>
    /// 加载配置。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <returns>配置实例。</returns>
    public static T Load<T>() where T : JsonConfig, new()
    {
        return Load<T>(new T().DefaultPath, new T().DefaultOptions);
    }

    /// <summary>
    /// 从指定路径加载配置。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="path">配置路径。</param>
    /// <returns>配置实例。</returns>
    public static T Load<T>(string path) where T : JsonConfig, new()
    {
        return Load<T>(path, new T().DefaultOptions);
    }

    /// <summary>
    /// 加载配置,使用指定选项。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="options">配置选项。</param>
    /// <returns>配置实例。</returns>
    public static T Load<T>(JsonConfigOptions options) where T : JsonConfig, new()
    {
        return Load<T>(new T().DefaultPath, options);
    }

    /// <summary>
    /// 从指定路径加载配置,使用指定选项。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="path">配置路径。</param>
    /// <param name="options">配置选项。</param>
    /// <returns>配置实例。</returns>
    public static T Load<T>(string path, JsonConfigOptions options) where T : JsonConfig, new()
    {
        var jco = options ?? GlobalOptions;
        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            T config = JsonSerializer.Deserialize<T>(json, jco.SerializerOptions);
            config.Path = path;
            config.Options = options;
            return config;
        }
        else if (jco.CreateNew)
        {
            T config = new();
            config.Path = path;
            config.Options = options;
            if (jco.SaveNew)
                config.Save();
            return config;
        }
        else
        {
            return null;
        }
    }

    /// <summary>
    /// 尝试加载配置。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="config">配置实例。</param>
    /// <returns>是否成功。</returns>
    public static bool TryLoad<T>(out T config) where T : JsonConfig, new()
    {
        return TryLoad(new T().DefaultPath, new T().DefaultOptions, out config);
    }

    /// <summary>
    /// 尝试从指定路径加载配置。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="path">配置路径。</param>
    /// <param name="config">配置实例。</param>
    /// <returns>是否成功。</returns>
    public static bool TryLoad<T>(string path, out T config) where T : JsonConfig, new()
    {
        return TryLoad(path, new T().DefaultOptions, out config);
    }

    /// <summary>
    /// 尝试加载配置,使用指定选项。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="options">配置选项。</param>
    /// <param name="config">配置实例。</param>
    /// <returns>是否成功。</returns>
    public static bool TryLoad<T>(JsonConfigOptions options, out T config) where T : JsonConfig, new()
    {
        return TryLoad(new T().DefaultPath, options, out config);
    }

    /// <summary>
    /// 尝试从指定路径加载配置,使用指定选项。
    /// </summary>
    /// <typeparam name="T">配置类型。</typeparam>
    /// <param name="path">配置路径。</param>
    /// <param name="options">配置选项。</param>
    /// <param name="config">配置实例。</param>
    /// <returns>是否成功。</returns>
    public static bool TryLoad<T>(string path, JsonConfigOptions options, out T config) where T : JsonConfig, new()
    {
        try
        {
            config = Load<T>(path, options);
            return true;
        }
        catch
        {
            config = null;
            return false;
        }
    }

    /// <summary>
    /// 保存配置。
    /// </summary>
    public void Save()
    {
        Save(Path, Options);
    }

    /// <summary>
    /// 保存配置到指定路径。
    /// </summary>
    /// <param name="path">配置路径。</param>
    public void Save(string path)
    {
        Save(path, Options);
    }

    /// <summary>
    /// 保存配置,使用指定选项。
    /// </summary>
    /// <param name="options">配置选项。</param>
    public void Save(JsonConfigOptions options)
    {
        Save(Path, options);
    }

    /// <summary>
    /// 保存配置到指定路径,使用指定选项。
    /// </summary>
    /// <param name="path">配置路径。</param>
    /// <param name="options">配置选项。</param>
    public void Save(string path, JsonConfigOptions options)
    {
        var jco = options ?? GlobalOptions;
        string json = JsonSerializer.Serialize(this, GetType(), jco.SerializerOptions);
        File.WriteAllText(path, json);
    }

    /// <summary>
    /// 尝试保存配置。
    /// </summary>
    /// <returns>是否成功。</returns>
    public bool TrySave()
    {
        return TrySave(Path, Options);
    }

    /// <summary>
    /// 尝试保存配置到指定路径。
    /// </summary>
    /// <param name="path">配置路径。</param>
    /// <returns>是否成功。</returns>
    public bool TrySave(string path)
    {
        return TrySave(path, Options);
    }

    /// <summary>
    /// 尝试保存配置,使用指定选项。
    /// </summary>
    /// <param name="options">配置选项。</param>
    /// <returns>是否成功。</returns>
    public bool TrySave(JsonConfigOptions options)
    {
        return TrySave(Path, options);
    }

    /// <summary>
    /// 尝试保存配置到指定路径,使用指定选项。
    /// </summary>
    /// <param name="path">配置路径。</param>
    /// <param name="options">配置选项。</param>
    /// <returns>是否成功。</returns>
    public bool TrySave(string path, JsonConfigOptions options)
    {
        try
        {
            Save(path, options);
            return true;
        }
        catch
        {
            return false;
        }
    }
}

/// <summary>
/// 提供与 <see cref="JsonConfig"/> 一起使用的选项。
/// </summary>
public sealed class JsonConfigOptions
{
    /// <summary>
    /// 初始化 <see cref="JsonConfigOptions"/> 类的新实例。
    /// </summary>
    public JsonConfigOptions() { }

    /// <summary>
    /// 将 <see cref="JsonConfigOptions"/> 实例的选项复制到新实例。
    /// </summary>
    /// <param name="options">要从中复制选项的选项实例。</param>
    public JsonConfigOptions(JsonConfigOptions options)
    {
        CreateNew = options.CreateNew;
        SaveNew = options.SaveNew;
        SerializerOptions = options.SerializerOptions;
    }

    /// <summary>
    /// 如果文件不存在,是否创建新配置。
    /// </summary>
    public bool CreateNew { get; set; } = true;

    /// <summary>
    /// 创建新配置后,是否立刻将其保存。
    /// </summary>
    public bool SaveNew { get; set; } = true;

    /// <summary>
    /// 用于序列化和反序列化的 <see cref="JsonSerializerOptions"/>。
    /// </summary>
    public JsonSerializerOptions SerializerOptions { get; set; } = new()
    {
        AllowTrailingCommas = true,
        Converters = { new JsonStringEnumConverter() },
        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
        NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals | JsonNumberHandling.AllowReadingFromString,
        PropertyNameCaseInsensitive = true,
        ReadCommentHandling = JsonCommentHandling.Skip,
        WriteIndented = true
    };
}

快速上手

JsonConfig.cs 添加到项目中。

新建 Settings.cs

public class Settings : JsonConfig
{
    public string MyString { get; set; }
}

这样快速加载和保存:

var settings = JsonConfig.Load<Settings>();
settings.MyString = "Hello!";
settings.Save();

更多示例

极简日志

public class Log : JsonConfig
{
    protected override string DefaultPath => $"Logs\\{DateTime.Now:yyyyMMdd}.json";

    protected override JsonConfigOptions DefaultOptions => new() { SaveNew = false };

    public List<string> Messages { get; set; } = new();
}
作者:AlexSJC
本文采用 CC BY-NC-ND 4.0 许可协议
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇