Using JSON to store application preferences and configuration

Download full source code.

Storing configuration preferences in the database is not a hard task. It usually involves storing the name of the preference, the value and the type in the database. Then when retrieving the data you perform some sort of cast.

The casts tend to be a bit painful, but it works.

This is the call -

1bool displayWidget = (bool) Convert.ChangeType(_preferenceManager.BadWayToCastToGetPreference("DisplayWidget"), typeof(bool));

And this is the called method -

1        public object BadWayToCastToGetPreference<T>(string name)
2        {
3            var preference = Convert.ChangeType(_context.Preferences.SingleOrDefault(p => p.Name == name).Value, typeof(T));
4            return preference;
5        }

But this quickly falls apart when you want to store a list of something, this requires a custom way of generating a string that represents the list. A common way I’ve seen is to store the values as a pipe delimited list.

For example if you wanted to store three cities Boston, New York and Seattle they would become “Boston|New York|Seattle” when stored in the database.

Now you need a write code to turn that back into a list of strings.

The problem gets worse when you want to store some custom types, for example an emergency contact shaped like -

1    public class EmergencyContact
2    {
3        public int Priority { get; set; }
4        public string EmailAddress { get; set; }
5    }
Or worse if you want to store a list of emergency contacts.

Rather than suffering all that pain, just use Json to serialize and deserialize the values. This makes life a lot easier.

I have a simple method to create the preference object that gets store in the database -

 1        private Preference CreatePreference(string name, string value, string type)
 2        {
 3            var preference = new Preference
 4            {
 5                Name = name,
 6                Value = value,
 7                Type = type,
 8                PreferenceID = Guid.NewGuid()
 9            };
10            return preference;
11        }

CreatePreference gets called like this for a simple string -

1            string defaultEmail = "admin@example.com";
2            Preference preference1 = CreatePreference("DefaultEmail", JsonConvert.SerializeObject(defaultEmail), defaultEmail.GetType().ToString());

And it’s the same when storing a more complex type.

1            EmergencyContact[] secondaryEmergencyContacts = new[]
2            {
3                new EmergencyContact{ EmailAddress = "tom@example.com", Priority = 1},
4                new EmergencyContact{ EmailAddress = "dick@example.com", Priority = 2},
5                new EmergencyContact{ EmailAddress = "harry@example.com", Priority = 3},
6            };
7            Preference preference6 = CreatePreference("SecondaryEmergencyContacts",
8                JsonConvert.SerializeObject(secondaryEmergencyContacts), secondaryEmergencyContacts.GetType().ToString());

To store these preferences in the database, it’s just a simple Entity Framework call -

1            _context.Preferences.Add(preference1);
2            _context.Preferences.Add(preference6);
3            _context.SaveChanges();

And then to get the preferences back out of the database you call -

1        public T GetPreference<T>(string name)
2        {
3            var preference =
4                JsonConvert.DeserializeObject<T>(_context.Preferences.SingleOrDefault(p => p.Name == name).Value);
5            return preference;
6        }

Some might complain that it is slower than direct casts, and yes, it probably is. But if you haven’t measured it you shouldn’t optimize it. You can always cache preferences. And it is a lot neater than the alternative.

Download full source code.

comments powered by Disqus

Related