One of the key features of my blog is there is no database. This was a deliberate design decision. My blog had to be pure HTML/CSS and jQuery. So then how do I store information that is needed to say, populate an rss feed? Good question my friend! Read on...

Up to this point I've had no need to store information as each 'page' or 'post' on my blog is a self contained entity. It only needs to know about itself.

However the need to populate an rss feed means that I now need to store some basic information about each blog post.

Still wanting to keep my no database ethos I decided to use the file system to store this information. I convert my website to pure HTML before deployment so using this method incurs no performance hit on the live site.

I could have gone with xml, used a flat file format or created a class structure and serialized it.

Instead I chose JSON.

The wonder that is JSON

Incase you've been living under a rock, JSON is now the defacto standard for transmitting human readable data objects consisting of key:value pairs.

It has been widely embraced and most of the major programming languages have native support for it. You can see its use in AJAX calls, Web Service APIs and there are even NOSQL databases (CouchDB and RavenDB come to mind) that use it internally to store information.

The beautify of JSON is how data is represented. Here's the JSON meta data file for this blog post:

{
    "title": "BlogMatrix. Storing Data Without a Database",
    "publish_date": "2013-11-05",
    "author": {
        "name": "Kestrel Blackmore",
        "url": "http://www.kestrelblackmore.com",
        "email": "me@kestrelblackmore.com"
    },
    "link": {
        "url": "/blog/blogmatrix-storing-data-without-database"
    },
    "meta_description": "How I store data without having a database for my blog engine BlogMatrix",
    "summary": "One of the key features of my blog is there is no database. This was a deliberate design decision. My blog had to be pure HTML/CSS and jQuery. So then how do I store information that is needed to say, populate an rss feed? Good question my friend! Read on..."
}

It's a simple "key":"value" representation separated by a ,. If you want a collection put the key/value pairs within {}.

This is not a full tutorial on JSON so you can read more on it here.

The Master Plan

Having decided to use flat files with JSON as the file format I came up with the following plan of attack:

  1. Create a JSON file for each blog post with the necessary meta data
  2. Create a function that reads in all the JSON files
  3. Use this information to populate the RSS feed
  4. Use this information to populate the home and archives pages
  5. Use this information to populate elements of the blog post page

Step 1. JSON file for each blog post

I created a new directory, in the root of the project, called _postmetadata to store all of the JSON files. I then created a JSON file for every blog post and populated it with the necessary meta data information

I gave an example of the format for the JSON file above.

Step 2. Function to read in JSON files

I created a static class PostMetaData that would read in all of the JSON files, sort them in reverse publish date order and return a bunch of dynamic objects. If you haven't used the dynamic object type in C# before you should. They are amazing!

Using C# you can decode a JSON file into a dynamic object and it will 'dynamically' create the JSON keys as properties on your object. Awesome!

Here's the code:

using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
public static class PostMetaData
{
    public static SortedDictionary LoadPostMetaData(string pPostMetaDataPath) {
        var files  = new DirectoryInfo(pPostMetaDataPath).GetFiles();
        var result = new SortedDictionary(new ReverseComparer(Comparer.Default));
        foreach(var file in files) {
            var bits = GetPostMetaData(file.FullName);
            if (bits != null)
                result.Add(bits.publish_date, bits);
        }
        return result;
    }
    public static dynamic GetPostMetaData(string pFilename) {
        dynamic metadata = null;
        using (var s = new StreamReader(pFilename)) {
            metadata = System.Web.Helpers.Json.Decode(s.ReadToEnd());
        }
        return metadata;
    }
}

Step 3. Populate the RSS feed

Now I can pass the dictionary of dynamic objects into my RSSSyndicator.GetFeed method and it will have all the information it needs to generate the RSS Feed for my blog. Read my previous blog post for more information on how I create my RSS Feed.

public static SyndicationFeed GetFeed(SortedDictionary pPostMetaData) {
    var feed = GetBlogInformation(_baseurl);
    feed.Items = GetPosts(_baseurl, pPostMetaData);
    return feed;
}

Step 4. Populate home and archives pages

I used to manually maintain the list of blog posts with hard coded HTML. It was easy enought to update but seeing as I have all the necessary information in the JSON files I've changed it to be dynamically created.

Here's my modified _Archives.cshtml partial:


@{
    var postData = PostMetaData.LoadPostMetaData(Server.MapPath('~/_postmetadata'));
}
<section id='blog'>
    <dl>
    @foreach(var post in postData) {
        <dd><a href='@post.Value.link.url'>@post.Value.title</a></dd>
    }
    </dl>   
</section>

Step 5. Populate blog post elements

I also decided to use some of the JSON meta data to populate some of the elements for each blog post.

At this stage I am only using it for the Title and Meta_Description. In future I may add Author and the Publish_Date.

var metadata = PostMetaData.GetPostMetaData(Server.MapPath("~/_postmetadata/00013.json"));
Page.Title = metadata.title;
Page.Meta_Description = metadata.meta_description;

Conclusion

With a little ingenuity and thinking outside the box I've come up with what I think is an elegant solution. To better understand how it all fits together check out the BlogMatrix GitHub repository.

Let me know your thoughts in the comments below!



comments powered by Disqus