How to Serialize and Deserialize JSON in C#

JSON serialization and deserialization in C# has become remarkably straightforward with the System.Text.Json namespace, introduced in .NET Core 3.0 as a modern alternative to Newtonsoft.Json.

The JsonSerializer class provides static methods to convert objects to JSON strings (Serialize) and parse JSON strings back into objects (Deserialize).

For basic serialization, you can simply call JsonSerializer.Serialize(object) on any object, and it will automatically convert public properties into their JSON representation.

Similarly, JsonSerializer.Deserialize<T>(jsonString) converts JSON back into strongly-typed objects. The process becomes even more powerful when combined with custom attributes like [JsonPropertyName] to control property naming and [JsonIgnore] to exclude specific properties from serialization.

When working with more complex scenarios, you can customize the serialization process using JsonSerializerOptions.

This allows you to control various aspects such as case sensitivity, indentation, handling of null values, and custom converters. For example, setting PropertyNameCaseInsensitive = true enables case-insensitive property matching during deserialization, while WriteIndented = true produces formatted JSON output.

It's also worth noting that System.Text.Json is designed with performance in mind, offering better performance compared to Newtonsoft.Json for most scenarios.

Example

// Define a class to serialize
public class Person
{
    public string Name { get; set; }
    [JsonPropertyName("birth_date")]
    public DateTime BirthDate { get; set; }
    [JsonIgnore]
    public int InternalId { get; set; }
}

// Serialization example
Person person = new Person 
{ 
    Name = "John Doe", 
    BirthDate = new DateTime(1990, 1, 1) 
};
string json = JsonSerializer.Serialize(person);

// Deserialization example
Person deserializedPerson = JsonSerializer.Deserialize<Person>(json);

// Using JsonSerializerOptions
var options = new JsonSerializerOptions
{
    WriteIndented = true,
    PropertyNameCaseInsensitive = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
string prettyJson = JsonSerializer.Serialize(person, options);

// Working with collections
List<Person> people = new List<Person> { person };
string jsonArray = JsonSerializer.Serialize(people);
List<Person> deserializedPeople = JsonSerializer.Deserialize<List<Person>>(jsonArray);
3
945

Related

Closing a SqlDataReader correctly prevents memory leaks, connection issues, and unclosed resources. Here’s the best way to do it.

Use 'using' to Auto-Close

Using using statements ensures SqlDataReader and SqlConnection are closed even if an exception occurs.

Example

using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlCommand cmd = new SqlCommand("SELECT * FROM Users", conn))
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine(reader["Username"]);
        }
    } // ✅ Auto-closes reader here
} // ✅ Auto-closes connection here

This approach auto-closes resources when done and it is cleaner and less error-prone than manual closing.

⚡ Alternative: Manually Close in finally Block

If you need explicit control, you can manually close it inside a finally block.

SqlDataReader? reader = null;
try
{
    using SqlConnection conn = new SqlConnection(connectionString);
    conn.Open();
    using SqlCommand cmd = new SqlCommand("SELECT * FROM Users", conn);
    reader = cmd.ExecuteReader();

    while (reader.Read())
    {
        Console.WriteLine(reader["Username"]);
    }
}
finally
{
    reader?.Close();  // ✅ Closes reader if it was opened
}

This is slightly more error prone if you forget to add a finally block. But might make sense when you need to handle the reader separately from the command or connection.

1
217

Measuring the execution time of C# methods is essential for performance optimization and identifying bottlenecks in your application.

The most straightforward approach uses the Stopwatch class from the System.Diagnostics namespace, which provides high-precision timing capabilities.

This approach is perfect for quick performance checks during development or when troubleshooting specific methods in production code.

Here's a practical example: Imagine you have a method that processes a large dataset and you want to measure its performance.

First, add using System.Diagnostics; to your imports. Then implement timing as shown below:

public void MeasurePerformance()
{
    Stopwatch stopwatch = new Stopwatch();
    
    // Start timing
    stopwatch.Start();
    
    // Call the method you want to measure
    ProcessLargeDataset();
    
    // Stop timing
    stopwatch.Stop();
    
    // Get the elapsed time
    Console.WriteLine($"Processing time: {stopwatch.ElapsedMilliseconds} ms");
    // Or use ElapsedTicks for higher precision
    Console.WriteLine($"Processing ticks: {stopwatch.ElapsedTicks}");
}

For more advanced scenarios, consider using the BenchmarkDotNet library, which offers comprehensive benchmarking with statistical analysis.

Simply install the NuGet package, decorate methods with the [Benchmark] attribute, and run BenchmarkRunner.Run<YourBenchmarkClass>() to generate detailed reports comparing different implementation strategies.

2
385

XML (Extensible Markup Language) is a widely used format for storing and transporting data.

In C#, you can create XML files efficiently using the XmlWriter and XDocument classes. This guide covers both methods with practical examples.

Writing XML Using XmlWriter

XmlWriter provides a fast and memory-efficient way to generate XML files by writing elements sequentially.

Example:

using System;
using System.Xml;

class Program
{
    static void Main()
    {
        using (XmlWriter writer = XmlWriter.Create("person.xml"))
        {
            writer.WriteStartDocument();
            writer.WriteStartElement("Person");

            writer.WriteElementString("FirstName", "John");
            writer.WriteElementString("LastName", "Doe");
            writer.WriteElementString("Age", "30");

            writer.WriteEndElement();
            writer.WriteEndDocument();
        }
        Console.WriteLine("XML file created successfully.");
    }
}

Output (person.xml):

<?xml version="1.0" encoding="utf-8"?>
<Person>
    <FirstName>John</FirstName>
    <LastName>Doe</LastName>
    <Age>30</Age>
</Person>

Writing XML Using XDocument

The XDocument class from LINQ to XML provides a more readable and flexible way to create XML files.

Example:

using System;
using System.Xml.Linq;

class Program
{
    static void Main()
    {
        XDocument doc = new XDocument(
            new XElement("Person",
                new XElement("FirstName", "John"),
                new XElement("LastName", "Doe"),
                new XElement("Age", "30")
            )
        );
        doc.Save("person.xml");
        Console.WriteLine("XML file created successfully.");
    }
}

This approach is ideal for working with complex XML structures and integrating LINQ queries.

When to Use Each Method

  • Use XmlWriter when performance is critical and you need to write XML sequentially.
  • Use XDocument when you need a more readable, maintainable, and flexible way to manipulate XML.

Conclusion

Writing XML files in C# is straightforward with XmlWriter and XDocument. Choose the method that best suits your needs for performance, readability, and maintainability.

3
375