ZetCode

C# JSON

last modified May 13, 2025

This C# JSON tutorial demonstrates how to handle JSON data using the built-in classes of the standard library. JSON is a widely used data format for exchanging information between applications, especially in web development and APIs. Understanding how to parse, serialize, and manipulate JSON in C# is essential for building modern .NET applications that interact with external data sources or services.

JSON

JSON (JavaScript Object Notation) is a lightweight format for data exchange. It is easy for humans to read and write while being efficiently parsed and generated by machines. The official Internet media type for JSON is application/json, and JSON files typically use the .json extension. JSON supports basic data types such as strings, numbers, booleans, arrays, and objects, making it flexible for representing complex data structures.

In this tutorial, we focus on working with JSON using the C# standard library. Additionally, there is a widely used third-party library called Json.NET, which offers extended functionality for JSON processing. While System.Text.Json is recommended for most new projects due to its performance and integration with .NET, Json.NET remains popular for its advanced features and compatibility.

System.Text.Json

The System.Text.Json namespace provides a high-performance, memory-efficient, and standards-compliant solution for working with JSON in C#. It supports serialization of objects into JSON text and deserialization of JSON text into objects, with built-in UTF-8 optimization for faster processing. This namespace is included in .NET Core 3.0 and later, and is the preferred way to handle JSON in modern C# applications.

C# JSON parse

The JsonDocument.Parse method parses a stream or string as UTF-8-encoded data representing a single JSON value into a JsonDocument. The stream is read to completion, and the resulting document provides a DOM-like API for navigating and extracting data from the JSON structure. This is useful when you need to inspect or manipulate JSON data without mapping it directly to C# types.

Program.cs
using System.Text.Json;

string data = @" [ {""name"": ""John Doe"", ""occupation"": ""gardener""}, 
    {""name"": ""Peter Novak"", ""occupation"": ""driver""} ]";

using JsonDocument doc = JsonDocument.Parse(data);
JsonElement root = doc.RootElement;

Console.WriteLine(root);

var u1 = root[0];
var u2 = root[1];
Console.WriteLine(u1);
Console.WriteLine(u2);

Console.WriteLine(u1.GetProperty("name"));
Console.WriteLine(u1.GetProperty("occupation"));

Console.WriteLine(u2.GetProperty("name"));
Console.WriteLine(u2.GetProperty("occupation"));

In the example, we parse a simple JSON string containing an array of objects. Each object represents a user with a name and occupation. We use JsonDocument to parse the string and access the root element, which is an array. We then extract individual elements and their properties using the provided API. This approach is helpful when working with dynamic or unknown JSON structures.

using JsonDocument doc = JsonDocument.Parse(data);

We parse the JSON string into a JsonDocument, which allows us to navigate the JSON structure using the DOM-like API. This is especially useful when the structure of the JSON is not known at compile time or when you need to access only a subset of the data.

JsonElement root = doc.RootElement;

We get the reference to the root element with the RootElement property. The root element can be an object, array, or primitive value, depending on the JSON data.

var u1 = root[0];
var u2 = root[1];
Console.WriteLine(u1);
Console.WriteLine(u2);

With the [] operator, we get the first and the second subelements of the JSON document. This allows us to access individual objects within the array and further inspect their properties.

Console.WriteLine(u1.GetProperty("name"));
Console.WriteLine(u1.GetProperty("occupation"));

We get the properties of an element with GetProperty. This method retrieves the value of a named property from a JSON object, enabling us to extract specific fields from the data.

$ dotnet run
[ {"name": "John Doe", "occupation": "gardener"},
  {"name": "Peter Novak", "occupation": "driver"} ]
{"name": "John Doe", "occupation": "gardener"}
{"name": "Peter Novak", "occupation": "driver"}
John Doe
gardener
Peter Novak
driver

C# JSON enumerate

In the example, we enumerate the contents of the root element, which is a JSON array. We use the EnumerateArray method to iterate over each object in the array, and then use EnumerateObject to access all properties of each object. This approach is useful for processing collections of data in JSON format, such as lists of users or items.

Program.cs
using System.Text.Json;

string data = @" [ {""name"": ""John Doe"", ""occupation"": ""gardener""}, 
    {""name"": ""Peter Novak"", ""occupation"": ""driver""} ]";

using var doc = JsonDocument.Parse(data);
JsonElement root = doc.RootElement;

var users = root.EnumerateArray();

while (users.MoveNext())
{
    var user = users.Current;
    System.Console.WriteLine(user);

    var props = user.EnumerateObject();

    while (props.MoveNext())
    {
        var prop = props.Current;
        Console.WriteLine($"{prop.Name}: {prop.Value}");
    }
}

We get the array of subelements using EnumerateArray. This method returns an enumerator that allows us to loop through each element in the JSON array, making it easy to process multiple items.

var users = root.EnumerateArray();

In a while loop, we go over the array of elements. For each element, we print the entire object and then enumerate its properties. This demonstrates how to traverse nested JSON structures and extract detailed information from each object.

while (users.MoveNext())
{
    var user = users.Current;
    Console.WriteLine(user);
...

In the second while loop, we go over the properties of each element. We use EnumerateObject to access all key-value pairs in the JSON object, allowing us to print or process each property individually.

var props = user.EnumerateObject();

while (props.MoveNext())
{
    var prop = props.Current;
    Console.WriteLine($"{prop.Name}: {prop.Value}");
}
$ dotnet run
{"name": "John Doe", "occupation": "gardener"}
name: John Doe
occupation: gardener
{"name": "Peter Novak", "occupation": "driver"}
name: Peter Novak
occupation: driver

C# JSON serialize

In the example, we convert a User object into a JSON string using JsonSerializer.Serialize. Serialization is the process of converting an object or data structure into a format that can be easily stored or transmitted, such as JSON. This is commonly used when sending data to web APIs or saving configuration files.

Program.cs
using System.Text.Json;

var user = new User("John Doe", "gardener", new MyDate(1995, 11, 30));

var json = JsonSerializer.Serialize(user);
Console.WriteLine(json);

record MyDate(int year, int month, int day);
record User(string Name, string Occupation, MyDate DateOfBirth);
$ dotnet run
{"Name":"John Doe","Occupation":"gardener",
    "DateOfBirth":{"year":1995,"month":11,"day":30}}

C# JSON deserialize

The JsonSerializer.Deserialize method parses the text representing a single JSON value into an instance of a specified type. This allows you to convert JSON data received from external sources into strongly-typed C# objects, making it easier to work with the data in your application.

Program.cs
using System.Text.Json;

string json = @"{""Name"":""John Doe"", ""Occupation"":""gardener"",
    ""DateOfBirth"":{""year"":1995,""month"":11,""day"":30}}";

var user = JsonSerializer.Deserialize<User>(json);

Console.WriteLine(user);

Console.WriteLine(user?.Name);
Console.WriteLine(user?.Occupation);
Console.WriteLine(user?.DateOfBirth);

record MyDate(int year, int month, int day);
record User(string Name, string Occupation, MyDate DateOfBirth);

The example parses the JSON string into an instance of the User type. After deserialization, you can access the properties of the object as you would with any C# class, enabling type-safe manipulation of the data.

C# JsonSerializerOptions

With JsonSerializerOptions, we can control the process of serialization with some options. For example, the WriteIndented option enables pretty printing, making the output more readable. Other options allow customization of property naming, handling of null values, and more.

Program.cs
using System.Text.Json;

var words = new Dictionary<int, string>
{
    {1, "sky"},
    {2, "cup"},
    {3, "odd"},
    {4, "cloud"},
    {5, "forest"},
    {6, "warm"},
};

var r = JsonSerializer.Serialize(words, 
    new JsonSerializerOptions { WriteIndented = true });

Console.WriteLine(r);

Console.WriteLine("---------------------");

var d = JsonSerializer.Deserialize<Dictionary<int, string>>(r);

foreach (var (k, v) in d!)
{
    Console.WriteLine($"{k}: {v}");
}

With the WriteIndented option set, we enable indentation for pretty printing. This is useful for debugging or when the JSON output needs to be human-readable, such as in configuration files or logs.

$ dotnet run
{
  "1": "sky",
  "2": "cup",
  "3": "odd",
  "4": "cloud",
  "5": "forest",
  "6": "warm"
}
---------------------
1: sky
2: cup
3: odd
4: cloud
5: forest
6: warm

C# Utf8JsonWriter

In the example, we create a new object and write it into a JSON string using Utf8JsonWriter. This class provides a high-performance, forward- only API for writing UTF-8 encoded JSON text. It is suitable for scenarios where you need to generate JSON dynamically or with fine-grained control over the output.

Program.cs
using System.Text.Json;
using System.Text;

using var ms = new MemoryStream();
using var writer = new Utf8JsonWriter(ms);

writer.WriteStartObject();
writer.WriteString("name", "John Doe");
writer.WriteString("occupation", "gardener");
writer.WriteNumber("age", 34);
writer.WriteEndObject();
writer.Flush();

string json = Encoding.UTF8.GetString(ms.ToArray());

Console.WriteLine(json);
$ dotnet run
{"name":"John Doe","occupation":"gardener","age":34}

In the example, we write a JSON string into a file. The data is prettyfied using the Indented option of JsonWriterOptions. Pretty printing makes the JSON easier to read and maintain, especially for configuration files or data meant for manual inspection.

Program.cs
using System.Text.Json;

string data = @" [ {""name"": ""John Doe"", ""occupation"": ""gardener""}, 
    {""name"": ""Peter Novak"", ""occupation"": ""driver""} ]";

JsonDocument jdoc = JsonDocument.Parse(data);

var fileName = @"data.json";
using FileStream fs = File.OpenWrite(fileName);

using var writer = new Utf8JsonWriter(fs, new JsonWriterOptions { Indented = true });
jdoc.WriteTo(writer);
$ cat data.json 
[
    {
    "name": "John Doe",
    "occupation": "gardener"
    },
    {
    "name": "Peter Novak",
    "occupation": "driver"
    }
]

C# JSON Utf8JsonReader

In the example, we read JSON data from a file with Utf8JsonReader. It provides a low-level API for reading JSON data token by token. This is useful for processing large JSON files or streams efficiently, as it avoids loading the entire document into memory.

Program.cs
using System.Text.Json;

var fileName = @"/home/user7/data.json";
byte[] data = File.ReadAllBytes(fileName);
Utf8JsonReader reader = new Utf8JsonReader(data);

while (reader.Read())
{
    switch (reader.TokenType)
    {
        case JsonTokenType.StartObject:
            Console.WriteLine("-------------");
            break;
        case JsonTokenType.EndObject:
            break;
        case JsonTokenType.StartArray:
        case JsonTokenType.EndArray:
            break;
        case JsonTokenType.PropertyName:
            Console.Write($"{reader.GetString()}: ");
            break;
        case JsonTokenType.String:
            Console.WriteLine(reader.GetString());
            break;
        default:
            throw new ArgumentException();

    }
}
$ dotnet run
-------------
name: John Doe
occupation: gardener
-------------
name: Peter Novak
occupation: driver

C# JSON parse async

The example reads all releases of the .NET Core framework, which are available as a JSON string on the project Github repository. It demonstrates how to use JsonDocument.ParseAsync to read and parse JSON data from a stream asynchronously, which is important for responsive applications that handle network or file I/O.

Program.cs
using System.Text.Json;

using var httpClient = new HttpClient();

var url = "https://raw.githubusercontent.com/dotnet/core/master/release-notes/releases-index.json";
var ts = await httpClient.GetStreamAsync(url);

using var resp = await JsonDocument.ParseAsync(ts);

var root = resp.RootElement.GetProperty("releases-index");

var elems = root.EnumerateArray();

while (elems.MoveNext())
{
    var node = elems.Current;
    Console.WriteLine(node);
}

C# HttpClient GetFromJsonAsync

The GetFromJsonAsync method sends a GET request to the specified URL and returns the value that results from deserializing the response body as JSON in an asynchronous operation. This method simplifies the process of fetching and parsing JSON data from web APIs, making it easy to integrate external data sources into your C# applications.

The method is an extension method from System.Net.Http.Json.

Program.cs
using System.Text.Json.Serialization;
using System.Net.Http.Json;

using var client = new HttpClient();

var url = "http://webcode.me/users.json";
var data = await client.GetFromJsonAsync<Users>(url);

if (data != null)
{
    foreach (var user in data.users)
    {
        Console.WriteLine(user);
    }
}

class Users
{
    public List<User> users { get; set; } = new();
}

class User
{
    [JsonPropertyName("id")]
    public int Id { get; set; }

    [JsonPropertyName("first_name")]
    public string FirstName { get; set; } = string.Empty;

    [JsonPropertyName("last_name")]
    public string LastName { get; set; } = string.Empty;

    [JsonPropertyName("email")]
    public string Email { get; set; } = string.Empty;

    public override string ToString()
    {
        return $"User {{ {Id}| {FirstName} {LastName}| {Email} }}";
    }
}

We create an asynchronous http request to a JSON resource. The JSON data is serialized into a list of User objects, allowing for easy iteration and processing of the data in C#.

var data = await client.GetFromJsonAsync<Users>(url);

The GetFromJsonAsync is a convenience method which transforms JSON resource into C# collections. It handles the HTTP request, response, deserialization, and error handling, reducing boilerplate code and improving productivity.

class Users
{
    public List<User> users { get; set; } = new();
}

We need to create a specific class for the List collection. This class acts as a container for the deserialized data, matching the structure of the JSON response.

class User
{
    [JsonPropertyName("id")]
    public int Id { get; set; }

    [JsonPropertyName("first_name")]
    public string FirstName { get; set; } = string.Empty;

    [JsonPropertyName("last_name")]
    public string LastName { get; set; } = string.Empty;

    [JsonPropertyName("email")]
    public string Email { get; set; } = string.Empty;

    public override string ToString()
    {
        return $"User {{ {Id}| {FirstName} {LastName}| {Email} }}";
    }
}

The JSON fields are mapped to class attributes using the JsonPropertyName attribute. This ensures that the C# properties correspond to the correct JSON fields, even if the names differ. Overriding ToString() provides a convenient way to display the object data.

$ dotnet run
User { 1| Robert Schwartz| rob23@gmail.com }
User { 2| Lucy Ballmer| lucyb56@gmail.com }
User { 3| Anna Smith| annasmith23@gmail.com }
User { 4| Robert Brown| bobbrown432@yahoo.com }
User { 5| Roger Bacon| rogerbacon12@yahoo.com }

Source

JSON serialization and deserialization

In this article we have worked with JSON data in C#.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all C# tutorials.