{"id":26849251,"url":"https://github.com/nucs/jsonsettings","last_synced_at":"2025-04-06T22:05:47.591Z","repository":{"id":26365965,"uuid":"104251804","full_name":"Nucs/JsonSettings","owner":"Nucs","description":"This library simplifies creating configuration for your C# app/service by utilizing the serialization capabilities of Json.NET to serialize nested (custom) objects, dictionaries and lists as simply as by creating a POCO and inheriting JsonSettings class.","archived":false,"fork":false,"pushed_at":"2025-02-11T11:38:47.000Z","size":265,"stargazers_count":78,"open_issues_count":7,"forks_count":18,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-30T21:33:27.028Z","etag":null,"topics":["configuration","json","json-schema","jsonsettings","newtonsoft","newtonsoft-json","preferences","settings"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Nucs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-20T18:15:32.000Z","updated_at":"2024-11-30T06:10:48.000Z","dependencies_parsed_at":"2025-03-30T21:32:56.565Z","dependency_job_id":"95325955-1e6f-4883-ae3f-aa250bc52b48","html_url":"https://github.com/Nucs/JsonSettings","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nucs%2FJsonSettings","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nucs%2FJsonSettings/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nucs%2FJsonSettings/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nucs%2FJsonSettings/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Nucs","download_url":"https://codeload.github.com/Nucs/JsonSettings/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247557767,"owners_count":20958047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","json","json-schema","jsonsettings","newtonsoft","newtonsoft-json","preferences","settings"],"created_at":"2025-03-30T21:32:52.089Z","updated_at":"2025-04-06T22:05:47.575Z","avatar_url":"https://github.com/Nucs.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"https://i.imgur.com/BOExs52.png\" width=\"25\" style=\"margin: 5px 0px 0px 10px\"/\u003e JsonSettings\n[![Nuget downloads](https://img.shields.io/nuget/vpre/Nucs.JsonSettings.svg)](https://www.nuget.org/packages/nucs.JsonSettings/)\n[![NuGet](https://img.shields.io/nuget/dt/Nucs.JsonSettings.svg)](https://github.com/Nucs/JsonSettings)\n[![GitHub license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/Nucs/JsonSettings/blob/master/LICENSE)\n\nThis library aims to simplify the process of creating configuration for your C# app/service \nby utilizing the serialization capabilities of [Json.NET](https://www.newtonsoft.com/json/help/html/SerializationGuide.htm)\nto serialize nested (custom) objects, dictionaries and lists as simply as by creating a `POCO` and inheriting `JsonSettings` class.\u003cbr/\u003e\n\n\n### Installation\n```sh\nPM\u003e Install-Package nucs.JsonSettings\n```\n\n## Table of Contents\n- [Features Overview](#features-overview)\n- [The Basics](#the-basics)\n- [Modules](#recovery)\n    - [Recovery](#recovery)\n    - [Versioning](#versioning)\n    - [Encryption](#encryption)\n    - [Autosave](#autosave)\n      - [Suspend Saving](#suspend-autosave)\n      - [WPF Support with INotificationChanged/INotificationCollectionChanged](#wpf-support-with-inotificationchangedinotificationcollectionchanged)\n      - [Throttled Save](#throttled-save)\n- [Dynamic Settings Bag](#dynamic-settings-bag)\n- [Changing JsonSerializerSettings](#changing-jsonserializersettings)\n- [Converters](#converters)\n- [Modulation Api](#modulation-api)\n- [License](https://github.com/Nucs/JsonSettings/blob/master/LICENSE)\n\n\nFeatures Overview\n---\n - Initialized in a fluent static API \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#the-basics)\u003c/span\u003e\n - Cross-platform targeting `netstandard2.0`\n - Modularity allowing easy extension and high control over behavior on a per-object level  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#modulation-api)\u003c/span\u003e\n - Autosaving on changes  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#autosave)\u003c/span\u003e\n   - Via `INotificationChanged`/`INotificationCollectionChanged` allowing WPF binding (with interval throttling support to avoid cpu overload)  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#inotificationchanged-and-wpf-support)\u003c/span\u003e\n   - Via `Castle.DynamicProxy` generated wrapper  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#proxification)\u003c/span\u003e\n - Versioning control  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#versioning)\u003c/span\u003e\n   - Offers protection mechanisms such as renaming file and loading default\n   - By changing version, it allows to introduce any kind of changes to the settings class\n - Customizable control over recovering from parsing exceptions  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#recovery)\u003c/span\u003e\n - AES256 Encryption via a key  \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#encryption)\u003c/span\u003e\n - Fully extensible with [Json.NET](https://www.newtonsoft.com/json/) 's capabilities, attributes and settings\n   - It'll be accurate to say that this library is built around [Json.NET](https://www.newtonsoft.com/json/)\n - `SettingsBag`, a `dynamic` option that uses a ConcurrentDictionary\u003cstring,object\u003e eliminating the need for hardcoding POCO class \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](#dynamic-settings)\u003c/span\u003e \n\nThe Basics\n---\nTest project: https://github.com/Nucs/JsonSettings/tree/master/tests/JsonSettings.Tests \u003cbr\u003e\nSerialization Guide: https://www.newtonsoft.com/json/help/html/SerializationGuide.htm \u003c/br\u003e\n\n`JsonSettings` is the base abstract class serving as the base class for all settings objects the user defines. \u003cbr\u003e\nCreation, loading is done through static API where saving is through the settings object API.\n\nHere is a self explanatory quicky of to how and what:\n\n* **Hardcoded settings**\n```C#\n//Step 1: create a class and inherit JsonSettings\nclass MySettings : JsonSettings {\n    //Step 2: override a default FileName or keep it empty. Just make sure to specify it when calling Load!\n    //This is used for default saving and loading so you won't have to specify the filename/path every time.\n    //Putting just a filename without folder will put it inside the executing file's directory.\n    public override string FileName { get; set; } = \"TheDefaultFilename.extension\"; //for loading and saving.\n\n    #region Settings\n\n    public string SomeProperty { get; set; }\n    public Dictionary\u003cstring, object\u003e Dictionary { get; set; } = new Dictionary\u003cstring, object\u003e();\n    public int SomeNumberWithDefaultValue { get; set; } = 1;\n    [JsonIgnore] public char ImIgnoredAndIWontBeSavedOrLoaded { get; set; }\n    \n    #endregion\n    \n    //Step 3: Override parent's constructors\n    public MySettings() { }\n    public MySettings(string fileName) : base(fileName) { }\n}\n\n//Step 4: Load\npublic MySettings Settings = JsonSettings.Load\u003cMySettings\u003e(\"config.json\"); //relative path to executing file.\n//or create a new empty\npublic MySettings Settings = JsonSettings.Construct\u003cMySettings\u003e(\"config.json\");\n\n//Step 5: Introduce changes and save.\nSettings.SomeProperty = \"ok\";\nSettings.Save();\n```\n\n* **Dynamic settings**\n    * Dynamic settings will automatically create new keys.\n    * Can accept any Type that Json.NET can serialize\n    * [`ValueType`s](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/value-types) are returned as `Nullable\u003cType\u003e`, therefore if a key doesn't exist - a null is returned.    \n```C#\n//Step 1: Just load it, it'll be created if doesn't exist.\npublic SettingsBag Settings = JsonSettings.Load\u003cSettingsBag\u003e(\"config.json\");\n//Step 2: use!\nSettings[\"key\"]  = \"dat value tho\";\nSettings[\"key2\"] = 123;\ndynamic dyn = Settings.AsDynamic();\nif ((int?)dyn.key2==123)\n    Console.WriteLine(\"explode\");\ndyn.Save(); /* or */ Settings.Save();\n```\n* **Encrypted settings**\n    * Uses AES/Rijndael\n    * Can be applied to any settings class because it is a module.\n```C#\nMySettings Settings = JsonSettings.Load\u003cMySettings\u003e(\"config.json\", q=\u003eq.WithEncryption(\"mysecretpassword\"));\nSettingsBag Settings = JsonSettings.Load\u003cSettingsBag\u003e(\"config.json\", q=\u003eq.WithEncryption(\"mysecretpassword\"));\n//or\nMySettings Settings = JsonSettings.Configure\u003cMySettings\u003e(\"config.json\")\n                     .WithEncryption(\"mysecretpassword\")\n               //or: .WithModule\u003cRijndaelModule\u003e(\"pass\");\n                     .LoadNow();\n\nSettingsBag Settings = JsonSettings.Configure\u003cSettingsBag\u003e(\"config.json\")\n                     .WithEncryption(\"mysecretpassword\")\n               //or: .WithModule\u003cRijndaelModule\u003e(\"pass\");\n                     .LoadNow();\n```\n\n* **Hardcoded Settings with Autosave**\n    * Automatic save will occur when changes detected on virtual properties\n    * All properties have to be virtual\n    * Requires package `nucs.JsonSettings.Autosave` that uses `Castle.Core`.\n```C#\nSettings x  = JsonSettings.Load\u003cSettings\u003e().EnableAutosave(); //call after loading\n//or:\nISettings x = JsonSettings.Load\u003cSettings\u003e().EnableIAutosave\u003cISettings\u003e(); //Settings implements interface ISettings\n\nx.Property = \"value\"; //Saved!\n```\n\n* **Dynamic Settings with Autosave**\n    * Automatic save will occur when changes detected\n    * note: SettingsBag has it's own implementation of EnableAutosave().\n```C#\n//Step 1:\nSettingsBag Settings = JsonSettings.Load\u003cSettingsBag\u003e(\"config.json\").EnableAutosave(); //call after loading\n//Unavailable for hardcoded settings yet! (ty netstandard2.0 for not being awesome on proxies)\n//Step 2:\nSettings.AsDynamic().key = \"wow\"; //Saved!\nSettings[\"key\"] = \"wow two\"; //Saved!\n```\n\nRecovery\n---\n`RecoveryModule` provides handling for `JsonException` when calling `JsonSettings.LoadJson` during the loading process.\nOn a scenario of exception/failure, one of the following actions can take place:\n\n- **RecoveryAction.Throw**\u003cbr/\u003e\n  Will throw JsonSettingsRecoveryException with the real exception as inner exception.\n- **RecoveryAction.LoadDefault**\u003cbr/\u003e\n  Default settings will be loaded without touching the existing file until next save.\n- **RecoveryAction.LoadDefaultAndSave**\u003cbr/\u003e\n  Default settings will be loaded and saved to disk immediately.\n- **RecoveryAction.RenameAndLoadDefault**\u003cbr/\u003e\n  Will append the version to the end of the faulty file's name and load the default settings and save to disk.\u003cbr/\u003e\n  i.e. `myfile.json` versioned `1.0.0.5` will be renamed to `myfile.1.0.0.5.json` if it fails on parsing and the new default settings will be saved as the original filename.\n\nAll recovery properties and methods are suited for inheritance so extending is quite easy.\n\n//TODO: add example\n\nVersioning\n---\n`VersioningModule\u003cT\u003e` provides the ability to enforce a specific version so when new changes are introduced to your Settings class (scheme),\na user-defined action can take place. Any of the following actions can be taken:\n- **VersioningResultAction.DoNothing**\u003cbr/\u003e\n  Will keep the old version if it was parsed by Json.NET successfully. otherwise RecoveryModule will handle the failure of loading.\n- **VersioningResultAction.Throw**\u003cbr/\u003e\n  Will throw JsonSettingsRecoveryException with the real exception as inner exception.\n- **VersioningResultAction.LoadDefault**\u003cbr/\u003e\n  Default settings will be loaded without touching the existing file until next save.\n- **VersioningResultAction.LoadDefaultAndSave**\u003cbr/\u003e\n  Default settings will be loaded and saved to disk immediately.\n- **VersioningResultAction.RenameAndLoadDefault**\u003cbr/\u003e\n  Will append the version to the end of the faulty file's name and load the default settings and save to disk.\u003cbr/\u003e\n  i.e. `myfile.json` versioned `1.0.0.5` will be renamed to `myfile.1.0.0.5.json` if it fails on parsing and the new default settings will be saved as the original filename.\n\nThere are two ways to specify which version to enforce.\n1. Pass the version when calling `WithVersioning`.\n2. Add `[EnforcedVersion(\"1.0.0.0\")]` attribute to your `IVersionable.Version` property definition.\u003cbr/\u003e\n    When dealing with inheritance/virtual override, the attribute of the lowest inherited class will be used.\n\n\n//TODO: example\n\n#### Policy\nA comparison between versions is done by the `Policy` which is a `Func\u003cVersion, Version, bool\u003e` passed during the construction of `VersioningModule\u003cT\u003e` or fallbacks to `static VersioningModule.DefaultPolicy` which can be changed.\u003cbr/\u003e\nIt is possible to change the static default policy by changing `VersioningModule.DefaultPolicy` although each `VersioningModule\u003cT\u003e` can be assigned its own policy.\u003cbr/\u003e\nBy default the versions must match exactly:\u003cbr/\u003e\n```C# \nstatic bool DefaultEqualPolicy(Version version, Version expectedVersion) {\n    return expectedVersion?.Equals(version) != false;\n}\n```\nEncryption\n---\nThe encryption used is AES256, the parsed json is decoded to UTF8 bytes, converted to encrypted bytes and then to base64 string encoding.\u003cbr/\u003e\nThe decision to save it as base64 is to make it easily copiable as a string.\n\n//TODO: example\n\nSpecial thanks to [Rijndael256](https://github.com/2Toad/Rijndael256) for their AES encryption implementation. \n\nAutosave\n---\nAutosaving detects changes in all virtual properties by creating a proxy wrapper using Castle.Core. \u003cbr/\u003e\nThe requirement for the class to be autosaved is for all public properties have to be virtual and the class to be non-sealed.\nAny properties that are not marked virtual will not work properly (not just won't autosave), therefore an `JsonSettingsException` is thrown if during proxification a non-virtual property is detected.\n\n#### Attributes\nProperties can be marked with `IgnoreAutosaveAttribute`  (`IgnoreJsonAttribute` will also work) to be excluded from the monitored properties for changes.\u003cbr/\u003e\nAll proxy wrapper classes generated with `ProxyGeneratedAttribute`.\n\n#### Requirements\n- All public properties must be virtual\n- Install `nucs.JsonSettings.Autosave` nuget package\n- Call `mySettings.EnableAutosave()` extension after calling `Load`\n\n//TODO: example\n\n#### Suspend Autosave\nIn some scenarios, there might be multiple close changes to the configuration object. Normally that would trigger multiple save calls.\n\nTo prevent that, the developer can create a `SuspendAutosave` object which will postpone the save to when `SuspendAutosave` will be disposed or `Resume` called.\nIf there were no changes between the allocation of `SuspendAutosave` object and disposal/resume then save won't be called.\n\n//TODO: example\n\nWPF Support with INotificationChanged/INotificationCollectionChanged\n---\nAny settings class can turn into a ViewModel with full autosave support making window settings and state persistence much simpler.\n\nWhen your settings class inherits `INotifyPropertyChanged`, upon calling `EnableAutosave`, \na different interceptor with `NotificationBinder` will be attached to the generated proxy object that'll listen to the settings class's:\n- `event PropertyChanged` calls\n- All properties that implement `INotifyPropertyChanged` will bind to their `event PropertyChanged`\n- All properties that implement `INotificationCollectionChanged` such as `ObservableCollection\u003cT\u003e`  will bind to their `event CollectionChanged`\n- All virtual properties that do not answer to the criteria above.\n\nSo evidently, objects inside ObservableCollection or other nested properties that are not in the settings class are not monitored for changes.\u003cbr/\u003e\u003cbr/\u003e\nAny properties that are not marked virtual will not work properly (not just won't autosave), therefore a `JsonSettingsException` is thrown if during proxification if a non-virtual property is detected.\n\n#### Requirements\n- Settings class inherit `INotifyPropertyChanged`\n- All public properties must be virtual\n- Install `nucs.JsonSettings.Autosave` nuget package\n- Call `mySettings.EnableAutosave()` extension after calling `Load`\n\nThrottled Save\n---\nUpcoming feature...\n\nDynamic Settings Bag\n---\nSettingsBag internally stores a key-value dictionary. \nAny type of Value can be passed as long as Json.NET knows how to serialize it. \u003cbr/\u003e\nSettingsBag has built-in feature for autosaving that can be enabled by calling EnableAutosave without WPF binding support. \u003cbr/\u003e\n\n//TODO: add example\n\nChanging JsonSerializerSettings\n---\nThe default settings are defined on `static JsonSettings.SerializationSettings`.\n```C#\npublic static JsonSerializerSettings SerializationSettings { get; set; } = new JsonSerializerSettings {\n    Formatting = Formatting.Indented, \n    ReferenceLoopHandling = ReferenceLoopHandling.Ignore, \n    NullValueHandling = NullValueHandling.Include, \n    ContractResolver = new FileNameIgnoreResolver(), \n    TypeNameHandling = TypeNameHandling.Auto\n};\n```\n\nTo alter the `JsonSerializerSettings`, it's best to understand how the library is resolving which settings to use during serialization/deserialization as follows:\n```C#\n/// \u003csummary\u003e\n///     Returns configuration based on the following fallback: \u003cbr/\u003e\n///     settings ?? this.OverrideSerializerSettings ?? JsonSettings.SerializationSettings ?? JsonConvert.DefaultSettings?.Invoke()\n///              ?? throw new JsonSerializationException(\"Unable to resolve JsonSerializerSettings to serialize this JsonSettings\");\n/// \u003c/summary\u003e\n/// \u003cparam name=\"settings\"\u003eIf passed a non-null, This is the settings intended to use, not any of the fallbacks.\u003c/param\u003e\n/// \u003cexception cref=\"JsonSerializationException\"\u003eWhen no configuration valid was found.\u003c/exception\u003e\nprotected virtual JsonSerializerSettings ResolveConfiguration(JsonSerializerSettings? settings = null) {\n    return settings\n           ?? this.OverrideSerializerSettings\n           ?? JsonSettings.SerializationSettings\n           ?? JsonConvert.DefaultSettings?.Invoke()\n           ?? throw new JsonSerializationException(\"Unable to resolve JsonSerializerSettings to serialize this JsonSettings\");\n}\n```\n1. `settings` parameter is an internal mechanism when handling defaults. If passed a non-null, This is the settings intended to use, not any of the following fallbacks.\n2. `this.OverrideSerializerSettings` is a property in every class inheriting `JsonSettings` allowing personalized settings per object.\n   The `OverrideSerializerSettings` property and `ResolveConfiguration` method are both `virtual` and can be overriden to redirect the resolving to where ever you see fit or with what-ever predefined value.\n3. `static JsonSettings.SerializationSettings` is the default for all `JsonSettings` objects.\n4. `static JsonConvert.DefaultSettings` is the default settings defined on a Json.NET level.\n\n\nConverters\n---\nDefining converters or changing the serialization settings globally can be done by adding a converter to `static JsonSettings.SerializationSettings` as follows:\u003cbr/\u003e\n```C#\n//call during app startup\nJsonSettings.SerializationSettings.Converters.Add(new Newtonsoft.Json.Converters.VersionConverter());\n```\nAlternatively per object setting can be done by setting or inheriting `JsonSettings.OverrideSerializerSettings` property but\nit is important to also specify the default configuration so `JsonSettings` behavior will remain persistent ([see more](#changing-jsonserializersettings)) .\n\n### JsonConverterAttribute\nBy far the easiest way to specify a converter is by specifying a `JsonConverterAttribute` on the property and Json.NET will do the rest.\n```C#\n[JsonConverter(typeof(ExchangeConverter))]\npublic ExchangeType Exchange { get; set; }\n```\n\n`JsonConverterAttribute` can also be specified on an interface property as it is used in `IVersionable` and will apply to any class inheriting it.\n\u003cbr/\u003eThis is the best approach for other libraries because by specifying an attribute, no matter what `JsonSerializerSettings` will be specified by the developer, Json.NET will always serialize this property with the specified converter.  \n```C#\npublic interface IVersionable {\n    [JsonConverter(typeof(Newtonsoft.Json.Converters.VersionConverter))]\n    public Version Version { get; set; }\n}\n```\n\n\nModulation Api\n---\nKey points\n- All modules are stored inside `JsonSettings`.`ModuleSocket Modulation { get; }`.\n- `ModuleSocket` stores all modules attached to this `JsonSettings` object.\n- Every settings object gets a new module object allocated for every module configured.\n- Attaching modules is done via static extensions \u003cspan style='font-size:11px; padding-left: 3px' \u003e[read more](https://github.com/Nucs/JsonSettings/blob/master/src/Fluent/FluentJsonSettings.cs) \u003c/span\u003e\n- All modules provided by the library have properties and methods that are suited for inheritance so extending is easy.\n\n//TODO: example + example with Construct\n\n### Execution Order\nThe events are many to allow as much interception as possible.\u003cbr\u003e\nThe event handlers do not return any data but instead they receive a reference of the object that can be modified and will be used in the next stage.\u003cbr\u003e\n**Loading**\n```C#\nevent BeforeLoadHandler BeforeLoad(JsonSettings sender, ref string source); //source is the file that will be loaded.\nevent DecryptHandler Decrypt(JsonSettings sender, ref byte[] data);\nevent AfterDecryptHandler AfterDecrypt(JsonSettings sender, ref byte[] data);\nevent BeforeDeserializeHandler BeforeDeserialize(JsonSettings sender, ref string data);\nevent AfterDeserializeHandler AfterDeserialize(JsonSettings sender);\nevent AfterLoadHandler AfterLoad(JsonSettings sender);\n```\nAnd in a case of `JsonException` during `LoadJson`\n```C#\n//recovered marks if a recovery from failure was successful, handled will prevent any further modules from attempting to recover.\n//if recovered is returned false, JsonSettingsException will be thrown with the original exception as inner exception\nevent TryingRecoverHandler TryingRecover(JsonSettings sender, string fileName, JsonException? exception, ref bool recovered, ref bool handled);\nevent RecoveredHandler Recovered(JsonSettings sender);\n```\n**Saving**\n```C#\nevent BeforeSaveHandler BeforeSave(JsonSettings sender, ref string destinition);\nevent BeforeSerializeHandler BeforeSerialize(JsonSettings sender);\nevent AfterSerializeHandler AfterSerialize(JsonSettings sender, ref string data);\nevent EncryptHandler Encrypt(JsonSettings sender, ref byte[] data);\nevent AfterEncryptHandler AfterEncrypt(JsonSettings sender, ref byte[] data);\nevent AfterSaveHandler AfterSave(JsonSettings sender, string destinition);\n```\n\n#### Cryptography / Encoding Decoding\nWhen attaching to `OnEncrypt` event, it'll push to the end of the event queue - meaning it will receive the data after all the events/modules that were attached to it before.\u003cbr\u003e\nWhen attaching to `OnDecrypt`, it is pushed to the beginning of the event queue.\u003cbr\u003e\nHence encryption/encoding and decryption/decoding is automatically in the right order.\u003cbr\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnucs%2Fjsonsettings","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnucs%2Fjsonsettings","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnucs%2Fjsonsettings/lists"}