You might know the term JSON and maybe even worked with it. But C# has a lot of functionality to handle JSON. You can read JSON from a file, generate JSON from objects, and even send JSON as an output from a C# API. In this article, I will show you a few things you should know when working with JSON in C#.
Things you should know
For this article, you should
- Have basic C# knowledge
- Have an account at ChatGPT
- Know how to read from files with C#
Table Of Contents
What Is JSON?
JSON stands for JavaScript Object Notation and it is one of the few formats that is easy to read for humans and computers. It isn’t a specific system format. You can find JSON in most systems and software. It’s great for storing information in files, or databases, or exchanging it between services.
It was being used in the early 2000s when the need for server-to-browser communication was needed. The idea was to create data exchange without using plugins (Flash of Java). From there, the JSON idea kept growing and we use it a lot these days. You might not even notice it.
One downside: JSON is a format that is written in plain text. It can be read by humans and if humans can read it, it is not a really wise idea to store sensitive information in a JSON file.
The contents of a JSON, which is actually just a string, is an object or an array of objects, as you might notice in the next chapter of this article. It looks a lot like JavaScript if you have ever worked with that. But JavaScript is never meant to be working with objects, but JSON is an object notation.
Why would we use JSON? Well, it’s language-independent. This means that I can let my C# application communicate with a Java application. If the Java application needs information with a JSON format file, I can let my C# application write that. If my C# application is an API, the Java application can send a request to my API. The API returns JSON, which the Java application can read.
Basic JSON Examples
There are tons of examples I can show you, but let’s start really simple. Look at the following JSON:
{
"title": "The Matrix",
"release_date": "1999-07-17",
"rating": 8.7
}
I think you know what this is: It’s about the movie The Matrix, which was released in 1999, and has a rating of 8.7. The rating is random.
See? You can read this. With a little fantasy, you can see the JSON as a C# object, especially with the curly brackets. It has properties (title, release_data, rating) and values (The Matrix, 1999-07-17, 8.7). The properties have no types. It’s either text, a number, or a boolean.
These properties are called ‘names’ in JSON. This is because a property has much more than just the name of the property.
Okay, let’s do another one:
[
{
"title": "The Matrix",
"release_date": "1999-03-31",
"rating": 8.7
},
{
"title": "Inception",
"release_date": "2010-07-16",
"rating": 8.8
}
]
It’s almost the same, but with a little difference: It now shows 2 movies and the first and last characters are brackets. This is an array of objects.
It is also possible to place an object in an object, like this:
[
{
"title": "The Matrix",
"release_date": "1999-03-31",
"rating": 8.7,
"main_actor": {
"name": "Keanu Reeves",
"age": 57,
"gender": "Male"
},
"seen": true
},
{
"title": "Inception",
"release_date": "2010-07-16",
"rating": 8.8,
"main_actor": {
"name": "Leonardo DiCaprio",
"age": 47,
"gender": "Male"
},
"seen": false
}
]
I now added the main actor to each movie. It could have been an array with all actors. Then we use the brackets and add more actors. But I think you get the idea.
Note the naming convention. There are no capital letters and the separation of words is done with ‘_’. We don’t do this in C#, so we should be aware of this when we want to load a JSON into C#.
I will be using the last example in the next chapters.
Converting JSON to C# Objects
Converting a JSON string, as I showed before, is really easy. You just put the JSON content in a string, deserialize the JSON to C# objects, and done!
But… We do need those C# objects. We can’t just create objects on the fly. If you want to import JSON into a C# object, you need objects that match the JSON names. The above example shows us which names we need to create and what data type we should use. Let’s create a movie object, the actor will be done later:
public class Movie
{
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public double Rating { get; set; }
public bool HasBeenSeen { get; set; }
}
As you can see I followed the names of the JSON. I used common sense with the property data types. Now we can convert the JSON to this C# object. To do this we need the namespace System.Text.Json or you can install Newtonsoft.Json, which is a great NuGet package that handles everything you need for JSON. I will be using System.Text.Json.
using System.Text.Json;
string json = @"[
{
""title"": ""The Matrix"",
""release_date"": ""1999-03-31"",
""rating"": 8.7,
""main_actor"": {
""name"": ""Keanu Reeves"",
""age"": 57,
""gender"": ""Male""
},
""seen"": true
},
{
""title"": ""Inception"",
""release_date"": ""2010-07-16"",
""rating"": 8.8,
""main_actor"": {
""name"": ""Leonardo DiCaprio"",
""age"": 47,
""gender"": ""Male""
},
""seen"": false
}
]";
List<Movie> movies = JsonSerializer.Deserialize<List<Movie>>(json);
foreach (Movie item in movies)
{
Console.WriteLine($"The movie {item.Title} has been released on {item.ReleaseDate} and has a rating of {item.Rating}");
}
The idea about System.Text.Json is that it will try to match the names from the JSON to the C# object and then set the value. But this doesn’t always work well. If you start the application now you might at least expect the title to have a value:

As you can see, it doesn’t work like we want it. But this can be solved without many problems.
Adding Attributes
Attributes help us configure how the JSON should be read. There are two things we can do:
- Change the names of the properties in our C# object so it matches the names in the JSON string.
- Tell the C# object properties what the correct names in the JSON string are with attributes.
I would never go for the first option. Simply because C# is built on naming conventions. The names of properties in C# are also important. So I am going to add some attributes to the Movie object properties.
If the name in the JSON is different than the property name in your C# object, you can add the attribute JsonPropertyName to those properties you want to map. If you don’t want or can map a property to a JSON name, don’t use the attribute.
The JsonPropertyName attribute has one parameter: The name of the JSON name. The C# property SeenBeenSeen is a good one. Because in the JSON it’s seen. The JsonPropertyName parameter would therefore be ‘seen’. Below is the whole C# object with all the properties and attributes:
public class Movie
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("release_date")]
public DateTime ReleaseDate { get; set; }
[JsonPropertyName("rating")]
public double Rating { get; set; }
[JsonPropertyName("seen")]
public bool HasBeenSeen { get; set; }
}
Running the application again shows this result:

I must note that Newtonsoft.Json handles this way better, but I am staying with the full .NET library for now.
Big JSON To C#
The example above is pretty simple. But in some cases, the JSON is really big and sometimes unreadable because of the amount of information. Let’s take a look at the JSON example below:
{
"movies": [
{
"title": "The Matrix",
"rating": 8.7,
"release_date": "1999-03-31",
"thumbnail": "https://example.com/the_matrix_thumbnail.jpg",
"main_actors": [
{
"age": 58,
"gender": "male",
"first_name": "Keanu",
"last_name": "Reeves"
},
{
"age": 56,
"gender": "male",
"first_name": "Laurence",
"last_name": "Fishburne"
},
{
"age": 56,
"gender": "female",
"first_name": "Carrie-Anne",
"last_name": "Moss"
}
],
"gross_income": 463517383,
"num_votes": 984563,
"directors": [
{
"age": 57,
"gender": "male",
"first_name": "Lana",
"last_name": "Wachowski"
},
{
"age": 56,
"gender": "male",
"first_name": "Lilly",
"last_name": "Wachowski"
}
],
"writers": [
{
"age": 57,
"gender": "male",
"first_name": "Lana",
"last_name": "Wachowski"
},
{
"age": 56,
"gender": "male",
"first_name": "Lilly",
"last_name": "Wachowski"
}
],
"tags": [
"science fiction",
"action"
],
"genres": [
"Action",
"Sci-Fi"
],
"language": "English",
"filming_locations": [
"Australia",
"United States"
],
"countries_of_origin": [
"United States"
],
"production_companies": [
"Warner Bros.",
"Village Roadshow Pictures"
]
},
{
"title": "Inception",
"rating": 8.8,
"release_date": "2010-07-16",
"thumbnail": "https://example.com/inception_thumbnail.jpg",
"main_actors": [
{
"age": 47,
"gender": "male",
"first_name": "Leonardo",
"last_name": "DiCaprio"
},
{
"age": 48,
"gender": "male",
"first_name": "Joseph",
"last_name": "Gordon-Levitt"
},
{
"age": 39,
"gender": "female",
"first_name": "Ellen",
"last_name": "Page"
}
],
"gross_income": 828322032,
"num_votes": 1350875,
"directors": [
{
"age": 51,
"gender": "male",
"first_name": "Christopher",
"last_name": "Nolan"
}
],
"writers": [
{
"age": 51,
"gender": "male",
"first_name": "Christopher",
"last_name": "Nolan"
}
],
"tags": [
"action",
"adventure",
"sci-fi"
],
"genres": [
"Action",
"Adventure",
"Sci-Fi"
],
"language": "English",
"filming_locations": [
"United Kingdom",
"United States"
],
"countries_of_origin": [
"United States",
"United Kingdom"
],
"production_companies": [
"Warner Bros.",
"Legendary Pictures",
"Syncopy"
]
},
{
"title": "Shrek 1",
"rating": 7.8,
"release_date": "2001-04-22",
"thumbnail": "https://example.com/shrek_1_thumbnail.jpg",
"main_actors": [
{
"age": 61,
"gender": "male",
"first_name": "Mike",
"last_name": "Myers"
},
{
"age": 60,
"gender": "male",
"first_name": "Eddie",
"last_name": "Murphy"
},
{
"age": 53,
"gender": "female",
"first_name": "Cameron",
"last_name": "Diaz"
}
],
"gross_income": 484409218,
"num_votes": 627334,
"directors": [
{
"age": 51,
"gender": "male",
"first_name": "Andrew",
"last_name": "Adamson"
},
{
"age": 49,
"gender": "male",
"first_name": "Vicky",
"last_name": "Jenson"
}
],
"writers": [
{
"age": 51,
"gender": "male",
"first_name": "Ted",
"last_name": "Elliott"
},
{
"age": 49,
"gender": "male",
"first_name": "Terry",
"last_name": "Rossio"
}
],
"tags": [
"animation",
"adventure",
"comedy"
],
"genres": [
"Animation",
"Adventure",
"Comedy"
],
"language": "English",
"filming_locations": [
"United States"
],
"countries_of_origin": [
"United States"
],
"production_companies": [
"DreamWorks Animation",
"Pacific Data Images"
]
}
]
}
You could expand the Movie object with all the properties, figuring out what properties to make. But… You don’t have to. You could use ChatGPT for this! Or Google Bard, if you don’t want to use ChatGPT.
Yes, ChatGPT is a great tool to create C# objects from a JSON string! Simply grab one object and copy-paste it into ChatGPT with the question if ChatGPT can create C# objects for it.
This will generate the following C# objects for you:
public class MainActor
{
public int age { get; set; }
public string gender { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
}
public class Director
{
public int age { get; set; }
public string gender { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
}
public class Writer
{
public int age { get; set; }
public string gender { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
}
public class Movie
{
public string title { get; set; }
public double rating { get; set; }
public string release_date { get; set; }
public string thumbnail { get; set; }
public List<MainActor> main_actors { get; set; }
public int gross_income { get; set; }
public int num_votes { get; set; }
public List<Director> directors { get; set; }
public List<Writer> writers { get; set; }
public List<string> tags { get; set; }
public List<string> genres { get; set; }
public string language { get; set; }
public List<string> filming_locations { get; set; }
public List<string> countries_of_origin { get; set; }
public List<string> production_companies { get; set; }
}
public class Root
{
public List<Movie> movies { get; set; }
}
After this, you can create the code to read the JSON into C# objects and do with it what you want.
Root rootMovies = JsonSerializer.Deserialize<Root>(json);
foreach (Movie item in rootMovies.movies)
{
Console.WriteLine($"The movie {item.Title} has been released on {item.ReleaseDate} and has a rating of {item.Rating}");
}
Getting A Specific Part From JSON
So. What’s that Root object? That is the first object which doesn’t have a name. You can see this by the first {at the beginning of the string. Many JSON strings start like this, but even if you start without the root object – directly to the movies-array – you won’t get any data. You need to get past the root object. But how?
Well, first you need to deserialize the JSON to a JsonElement. This can be compared to an anonymous object from which you can call the properties. Next, you can get the specific property from said JsonElement and deserialize that to the data type you want, List<Movie> in this case.
Sounds complicated? Nah, it’s just an extra step you need to take to avoid loading A LOT of data.
JsonElement jsonData = JsonSerializer.Deserialize<JsonElement>(json);
List<Movie> movies = jsonData.GetProperty("movies").Deserialize<List<Movie>>();
foreach (Movie item in movies)
{
Console.WriteLine($"The movie {item.Title} has been released on {item.ReleaseDate} and has a rating of {item.Rating}");
}
Converting C# Objects To JSON
I must admit that I didn’t convert C# objects to JSON. If I work on an application that spits out JSON it’s because it is doing that automatically (REST API). But I do write some JSON to databases.
Sometimes you have a lot of information that can’t be stored in a table because it’s extra information that belongs to an entity. In that case, I need to convert the C# object, with all properties and values, to a JSON string.
This is pretty simple since most information is already given in the previous chapter. Here I used Deserialize to convert JSON to a C# object, or objects.
As you might have figured out, there is a Serialize. If you didn’t, don’t be ashamed. Most people didn’t get it when I gave this lesson in front of a whole classroom of 60 needy eyes.
Here is the code on how to do it:
List<Movie> movies = new()
{
new Movie
{
Title = "The Matrix",
ReleaseDate = new DateTime(1999, 3, 31),
Rating = 8.7,
HasBeenSeen = true
},
new Movie
{
Title = "Shrek",
ReleaseDate = new DateTime(2001, 5, 18),
Rating = 7.8,
HasBeenSeen = true
},
new Movie
{
Title = "Inception",
ReleaseDate = new DateTime(2010, 7, 16),
Rating = 8.8,
HasBeenSeen = true
},
new Movie
{
Title = "Jaws",
ReleaseDate = new DateTime(1975, 6, 20),
Rating = 8.0,
HasBeenSeen = false
}
};
string json = JsonSerializer.Serialize(movies);
Console.WriteLine(json);
It’s that easy! Just create your C# objects, with values, and let the JsonSerializer serialize the object to a JSON. The string json contains the JSON string (duh!) which you can store in a database, file, or send to an API that needs the information.
Validating JSON
The idea behind JSON is that it’s lightweight and easy to read, edit, and send to other systems. But because it is so easy to edit it is important that your application receives the JSON it can handle/manage. Therefore it’s important to validate the JSON before handling it.
To validate incoming JSON we use a schema. This schema can be compared to a C# class. The schema will have all the properties and types that are expected. A schema is JSON too, but it looks a bit different:
{
'type': 'object',
'properties': {
'title': { 'type': 'string' },
'rating': { 'type': 'integer' },
'release_date': { 'type': 'string', 'format': 'date-time' }
},
'required': ['title', 'rating', 'release_date']
}
This is a single object which you can figure out by the first type (type: object). Then we define the properties of the JSON. Each property gets a type. After the properties, we can note which properties are required.
Before I show you the C# code to create such a schema and serialize some JSON, I must note that I had some problems with the escaping of the string. First I used the @ to escape the characters who were needed. But now I have to explicitly escape the characters. I don’t know why and I am trying to figure it out, but sadly… I didn’t find anything that could help me out.
Let’s put it to work. Let’s deserialize a JSON with the use of a schema. First, the schema and a single object of Movie in JSON:
string jsonData = "{" +
"\"title\": " +
"\"The Matrix\", " +
"\"rating\": 8, " +
"\"release_date\": \"1999-03-31\"" +
"}";
string jsonSchema = "{ " +
"\"type\": \"object\", " +
"\"properties\": { " +
"\"title\": { \"type\": \"string\" }, " +
"\"release_date\": { \"type\": \"string\", \"format\": \"date-time\" }, " +
"\"rating\" : { \"type\": \"number\" }" +
"}, " +
"\"required\": [\"name\", \"dateOfBirth\"] }";
using var dataDocument = JsonDocument.Parse(jsonData);
using var schemaDocument = JsonDocument.Parse(jsonSchema);
The last two lines parse the strings into JsonDocuments. This helps to examine the contents and structure of the JSON. We need these to get the properties from both JSON strings.
Note that the rating in the data doesn’t have quotes. If you surround it with quotes, JSON will think it’s a string. Just like with C#.
Next is checking each property on validity. This is a bit more code than you would assume (or expect). I placed this in a separate method:
bool ValidateJson(JsonElement data, JsonElement schema)
{
if (schema.TryGetProperty("properties", out var properties))
{
if (properties.TryGetProperty("release_date", out var releaseDateSchema) && data.TryGetProperty("release_date", out var releaeDateData))
{
if (releaeDateData.ValueKind != JsonValueKind.String || !DateTime.TryParse(releaeDateData.GetString(), out _))
return false;
DateTime releaseDate = DateTime.Parse(releaeDateData.GetString());
if (releaseDate < new DateTime(1900, 1, 1) || releaseDate > DateTime.Now)
return false;
}
else
return false;
if (properties.TryGetProperty("title", out var titleSchema) && data.TryGetProperty("title", out var titleData))
{
if (titleData.ValueKind != JsonValueKind.String)
return false;
}
else
return false;
if (properties.TryGetProperty("rating", out var ratingSchema) && data.TryGetProperty("rating", out var ratingData))
{
if (ratingData.ValueKind != JsonValueKind.Number)
return false;
}
else
return false;
}
return true;
}
This method will receive the JSON data and the schema. With this information each property of the schema and the data will be compared, parsed, and checked. If something is wrong (type, value) a false is returned.
If you run the code all will be good. But if you change the release_date property in the data to releasedate, you will get an invalid JSON.
This way you keep a guard on the structure of JSON. Yes, it is a bit more code than we would expect, but it’s pretty straightforward and controllable. You could make this easier with a loop or something. But you can figure that out by yourself. I just want to tell you how to start.
Conclusion
Alright, this took me a lot more time than expected. But I finished it. It’s funny when you start something you have been using for a long time, there is much more to it than you might think.
Anyway, JSON. You will use it one day. Especially when working with APIs (calling and retrieving data). But C# and .NET are smart enough to parse JSON to C# objects, so you can continue with your code. Know how to generate C# objects from JSON information.
If you retrieve information and you want to make sure the structure of the retrieved JSON is correct, you can write a validation on that retrieved JSON. Yes, it will take some time, but it’s worth it.
JSON: The most powerful interchangeable format. I can’t think of a world without it.

