Optimal way to store objects in AppConfig.json

Viewed 94

My AppConfig.json:

{
     "MyTimeZone: "CET",
     "RegularString" : "SomeValue",
     "AnArray" : ["1","2"]
}

My POCO class:

public class Settings
{
     public TimeZoneInfo MyTimeZone { get; set; }
     public string RegularString { get; set; }
     public IList<string> AnArray { get; set; }
}

Registry.cs:

var configuration = GetConfiguration("AppSettings.json");
services.Configure<Settings>(configuration.GetSection("Settings"));

This of course does not bind "CET" into a valid TimeZoneInfo object. Now the question is what is the best place in my application (a web app) to convert from string to TimeZoneInfo? Is there a way to automatically convert string config values to objects based on certain rules without creating custom converters?

2 Answers

Reference Use DI services to configure options

services.AddOptions<Settings>()
    .Configure<IConfiguration>((setting, configuration) => {
        var section = config.GetSection("Settings");
        //This will populate the other properties that can bind by default
        section.Bind(setting);

        //this will extract the remaining value and set it mnually
        string value = section.GetValue<string>("MyTimeZone");
        TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(value);
        setting.MyTimeZone = info;
    });

The complex setting value can be extracted directly from configuration via DI and used to create the time zone and apply it to the settings.

It just my personal opinion but I prefer the MyTimeZone to be a json object instead only a string. Consider the following:

"Settings": {
    "MyTimeZone": {
      "ConfigureTimeZoneById":  "CET"
    },
    "RegularString": "SomeValue",
    "AnArray": [ "1", "2" ]
  }

MyTimeZone.ConfigureTimeZoneById is not part of the actual data object. It's just proxy to bind object to configuration. This how TimeZone class might look like:

public class TimeZone
    {
        private string configureTimeZoneById { get; set; }
        public string ConfigureTimeZoneById
        {
            get { return configureTimeZoneById; }
            set
            {
                configureTimeZoneById = value;
                InitializeTimeZone(value);
            }
        }
        public string TimeZoneId { get; set; }
        public string OtherProperties { get; set; }

        private void InitializeTimeZone(string id)
        {
            var getTimeZone = TimeZonesDataset().FirstOrDefault(tzon => tzon.TimeZoneId.Equals(id));
            if (getTimeZone != null)
            {
                this.TimeZoneId = getTimeZone.TimeZoneId;
                this.OtherProperties = getTimeZone.OtherProperties;
            }
        }







        //dummy dataset
        private List<TimeZone> TimeZonesDataset() => new List<TimeZone> {
            new TimeZone{TimeZoneId = "CET", OtherProperties = "Dummy properties to prove point"},
            new TimeZone{TimeZoneId = "GMT", OtherProperties = default},
        };

       
Related