How To Parse JSON In C# .NET

I recently came across a project that was doing something simple – reading a JSON config file. But the way in which it parsed the JSON was perplexing to me. It seemed like the most convoluted way of reading JSON data I had ever seen. In an attempt to show the other developer the light, I quickly googled for an existing tutorial on how parsing JSON data was actually really easy with JSON.NET. To my amazement, many of the top results were doing the same crazy things this developer was doing.

So this is the tutorial I wish I could have sent on. This is how you parse JSON in C# .NET.

Installing JSON.NET for parsing JSON in C#

If you are working on a ASP.NET Core project before .NET Core 3.0, you likely have JSON.NET installed already. But if you are working on a Console Application or a Class Library, you will need to run the following from your package manager console to install it.

Install-Package Newtonsoft.Json

Our Example JSON Document

For the purposes of this tutorial, we want to have a really simple example JSON document to work with. That document will look like so :

{
  "MyStringProperty": "StringValue",
  "MyIntegerProperty": 1,
  "MySubDocument": {
    "SubDocumentProperty": "SubDocumentValue"
  },
  "MyListProperty": [
    1,
    2,
    3
  ]
}

I’ve saved this to a file, and all I’m doing is loading it into a string in a console application :

static void Main(string[] args)
{
    var myJsonString = File.ReadAllText("myfile.json");
}

Next we will take this string, and actually look at how we extract data from it.

Using JObject

This in my opinion is the very worst way to parse a large JSON document, but seems to be the immediate answer in any stackoverflow question surrounding JSON and C#. To me it relies on magic strings, is brittle as hell, and in general is overly complex.

Let’s look at how we might get a simple string property using a JObject :

static void Main(string[] args)
{
    var myJsonString = File.ReadAllText("myfile.json");
    var myJObject = JObject.Parse(myJsonString);
    Console.WriteLine(myJObject.SelectToken("MyStringProperty").Value<string>());
}

Eh, it’s alright, but relies on us passing in a magic string to find the property. It’s not terrible, but it’s not great either.

What about if we want to a subdocument? Well at first thought you may think you can use the well known XPath query that is typically used to parse XML files. You would be wrong. For reasons, there is a different query language called JSONPath that instead uses dot notation. In some respects it makes sense because JSON doesn’t have all the features XML has (attributes, namespaces etc), but it’s also kinda annoying to have to learn another set of notation.

Anyway, back to our sub document query  :

myJObject.SelectToken("$.MySubDocument.SubDocumentProperty").Value<string>()

If we want to grab our entire list object :

var myList = myJObject.SelectTokens("$.MyListProperty").Values<int>().ToList();
Console.WriteLine(myList[1].ToString());

So far, we’ve just been grabbing individual values. What if we want the entire document to be mapped? Forget about it. Mapping each item individually to a larger class would be torture (And yet I see people do this all the time).

The only reason to use JObject is if you want an individual item/property and don’t care about the majority of the document.

Using Dynamic JToken

Another dud way of parsing JSON is using JToken to cast the entire JSON document to a dynamic object. For example :

static void Main(string[] args)
{
    var myJsonString = File.ReadAllText("myfile.json");
    dynamic jToken = JToken.Parse(myJsonString);
    Console.WriteLine(jToken.MyStringProperty);
    Console.ReadLine();
}

This works and is pretty easy to get going, but suffers from some major flaws. The biggest being that the casing of your JSON document now becomes incredibly important to how your dynamic object looks. For example :

"MyStringProperty" => jToken.MyStringProperty
"myStringProperty" => jToken.myStringProperty

Given that JSON is typically snake or camel case, and properties in C# are pascal case, someone is going to have to give in and change their casing style.

This is also ignoring the fact that you are now locked into using dynamic objects which come with their own set of headaches around dynamic typing.

In my opinion, similar to JObject, it’s not worth using this method to parse entire JSON documents. Maybe if you need access to a single property and you prefer using a C# dynamic object over using JSONPath, otherwise forget about it.

Using JsonConvert

This, in my opinion, is the only way to convert JSON to a C# Object. And it’s dead easy!

First we create a C# class that matches what we have in JSON :

class MyJsonType
{
    public string MyStringProperty { get; set; }

    public int MyIntegerProperty { get; set; }

    public MyJsonSubDocumentType MySubDocument { get; set; }

    public List<int> MyListProperty { get; set; }
}

class MyJsonSubDocumentType
{
    public string SubDocumentProperty { get; set; }
}

Then with a single line, we can convert a JSON string into a strongly typed object :

var myJsonObject = JsonConvert.DeserializeObject<MyJsonType>(myJsonString);
Console.WriteLine(myJsonObject.MyStringProperty);
Console.ReadLine();

No fiddling around with paths, no worrying about type conversion, it just works. When it comes to accessing things like our list, because JSON.NET deserializes it straight to a list object, there is no worrying about casting or anything like that. For example, this works straight out of the box :

myJsonObject.MyListProperty.First()

Summary

9 times out of 10, you are going to want to use the JsonConvert option. It deserializes the entire JSON doc to a class which for the most part is going to be what you are doing for. The only time you should really be using JObject is when you want a very small subset of the document (Preferably just one or two items) – otherwise the leg work in mapping individual properties is just crazy.

8 thoughts on “How To Parse JSON In C# .NET”

  1. Hello.

    Do you still consider this the best way to deserialize, even with many fields? I have 50 lines of JSON properties, and to deserialize them I had to make a class with the same 50 lines of string parameters; this seems a little tedious, and like a very hard-coded approach..? This is what my JsonProperties class ends up looking like: https://pastebin.com/EKyn8NS0

    Id love to hear your thoughts on the matter. 🙂

    Reply
    • If you intend to use all 50 properties then yes, this is the best way. If you only need a single property from a large document, then using one of the other methods is a bit easier.

      Reply
    • For the 50 object class, in visual studio, I just found the Edit, Paste Special, Paste JSON as Class via a reddit post. Create a new class file, “paste special” your JSON string, and watch it build all the class code. Trying it out for a test project

      Reply
  2. Yea Bro Nice Article I’m actually here for the web jobs article and hoping that article is current for the craziness of Core 3.1 (breaking changes and Generic Host ) but yea I saw that JObject crap and almost hurled at the confusion it presented and just shook my head and wondered why in God’s name would anyone want to do that … ?

    Reply
  3. Wade … very nice presentation of the options (and inefficiencies) that are used today to parse json docs. I was looking for ways to simplify getting access to several elements of a complex json payload and was struggling to find a nice solution that was working for my use case. After reading your article, the light bulb came on (because of your superb write-up and examples) and i was able to Deserialize easily into my set of c# objects.

    Reply
  4. A typical json file has many entries with the same structure. How do you search for a matching entry and display the data for that record? I’ve looked at a number of examples and none have given a working example.

    Reply
  5. When one is reading a json file where the content is unknown in structure, and the items must be determine based on content….this can be quite a challenge. Very hard to find a C# 6.0 example (NOT NewtonSoft]

    Reply

Leave a Comment