JSON Import In .NET

by Anton 22. July 2011 13:37

Bantam Is Quitting Services

We as teamaton were using bantam for all of our todos. At the beginning of this year bantam was bought by ConstantContact, and they announced that bantam will cease services as of July 1. Since we are developing our own todo management tool (see our blog), we decided to push the development and use it instead of bantam.

Of course we wanted to take all of our todos with us. We used bantams export feature which gave us a JSON-file with all our tasks (closed and open ones). So I took on the task to write an JSON import feature into our tool.

Json.NET

After a bit of researching, I found that the library Json.NET would suit our import needs perfectly. Applying the deserialization was pretty straightforward – the documentation helped a lot. Here is the code from the Import controller:

[HttpPost]
public ActionResult Import(HttpPostedFileBase file)
{
    var todos = new List<Todo>();
    if (file != null && file.ContentLength > 0)
    {
        var streamReader = new StreamReader(file.InputStream);
        string text = streamReader.ReadToEnd();
        streamReader.Close();
 
        var bantamTodos = JsonConvert.DeserializeObject<IList<BantamTodo>>(text) as List<BantamTodo>;
        todos = bantamTodos.Select(bantamTodo => bantamTodo.ConvertToTodo()).ToList();
        _todoRepository.SaveImport(todos);
    }
 
    return RedirectToAction("List");
}

It just opens the file, extracts the content as a string, deserializes the string into a list of bantam todos, and then converts these bantam todos into our “normal” todos.

Indirection Via BantamTodo-Class

As you can see, I did not convert the JSON directly into our Todo-class. You can use attributes and the converter class to deserialize JSON into a class of your liking. There are two reasons, why I did not choose to do so: I did not want to load the Todo-class with attributes and converters, and I thought it would be easier to introduce a middle class (BantamTodo), which poses as a container and converter.

I used a nice tool, to take a good look into the original JSON-file: JSON Viewer.

JSON Viewer

With the information about the structure of the JSON file I started implementing via the TDD pattern. Here is my test class, which tests the deserialization of the the bantam todos and the conversion from the class BantamTodo to Todo:

[Test]
public void Should_Import_BantamToDo_FromJson()
{
    var jsonToDo = ArrangeTaskAsJson();
    var bantamToDo = JsonConvert.DeserializeObject<BantamTodo>(jsonToDo);
 
    bantamToDo.Categoy.Should().Be.EqualTo("Organisation");
    bantamToDo.Complete.Should().Be.EqualTo(true);
    bantamToDo.Created_At.Should().Be.EqualTo(new DateTime(2011, 6, 30, 0, 41, 57));
    bantamToDo.Due.Should().Be.EqualTo(new DateTime(2011, 7, 1));
    bantamToDo.Author.Name.Should().Be.EqualTo("Anton");
    bantamToDo.Assigned_To.Name.Should().Be.EqualTo("Oliver");
    bantamToDo.Related_To[0].Name.Should().Be.EqualTo("ToDo-Management Tool");
    bantamToDo.Name.Should().Be.EqualTo("Entwicklung nach Gebieten Personen zuordnen - Verantwortliche, Blogs, etc.");
    bantamToDo.Description.Should().Be.EqualTo("some good description");
    bantamToDo.Flagged.Should().Be.EqualTo(true);
}
 
[Test]
public void Should_Convert_BantamToDo_ToTodo()
{
    var jsonToDo = ArrangeTaskAsJson();
    var bantamToDo = JsonConvert.DeserializeObject<BantamTodo>(jsonToDo);
    var todo = bantamToDo.ConvertToTodo();
 
    todo.Status.Should().Be.EqualTo(bantamToDo.Complete ? Status.Closed : Status.Open);
    todo.Description.Should().Contain(bantamToDo.Name);
    todo.Description.Should().Contain(bantamToDo.Description);
    todo.Tags.Select(t => t.Name).Should().Contain(bantamToDo.Categoy);
    foreach (var bantamProject in bantamToDo.Related_To)
        todo.Tags.Select(t => t.Name).Should().Contain(bantamProject.Name);
    todo.DateCreated.Should().Be.EqualTo(bantamToDo.Created_At);
    todo.DateCompleted.Value.Date.Should().Be.EqualTo(bantamToDo.Due);
    todo.DateDue.Should().Be.EqualTo(bantamToDo.Due);
    todo.Creator.Name.Should().Be.EqualTo(bantamToDo.Author.Name);
    todo.Assignee.Name.Should().Be.EqualTo(bantamToDo.Assigned_To.Name);
    todo.Priority.Value.Should().Be.EqualTo(bantamToDo.Flagged ? 2 : 0);
}

The implementation was pretty straightforward. Since it was my first time working with MVC, and also my first time working with JSON, it took me some time. All in all – research, export and meetings included – it took me about 12 hours.

If you have any suggestions as to improvement I would appreciate them. If you are trying to import JSON into .NET yourself, I hope that this article helps.

Comments (1) -

Joyce Burgy United States
3/17/2015 12:25:17 AM #

Hi, I believe your blog could be having browser compatibility issues. When I take a look at your site in Safari, it looks fine but when opening in Internet Explorer, it has some overlapping issues. I just wanted to give you a quick heads up! Aside from that, wonderful blog!

Comments are closed

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for javascript. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our children. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.