JSON Serialization in C#: Techniques and Best Practices

JSON (JavaScript Object Notation) is a widely used format for data exchange in modern applications. Whether you are building RESTful APIs, persisting configuration settings, or communicating between services, efficient JSON serialization and deserialization are crucial in C# applications.

This guide explores advanced JSON serialization techniques, best practices, and performance optimizations using C# with .NET, focusing on System.Text.Json and Newtonsoft.Json libraries.

Understanding JSON Serialization in C#

Serialization is the process of converting an object into a JSON string, while deserialization transforms a JSON string back into an object. C# provides two primary libraries for JSON handling:

  1. System.Text.Json (built-in since .NET Core 3.0, preferred for performance)

  2. Newtonsoft.Json (widely used, feature-rich, supports legacy .NET versions)

Choosing Between System.Text.Json and Newtonsoft.Json

System.Text.Json offers better performance and is the default serializer in .NET Core and .NET 5+. However, Newtonsoft.Json provides advanced features like polymorphic serialization, extensive customization, and broad adoption.

FeatureSystem.Text.JsonNewtonsoft.Json
PerformanceFasterSlower (more overhead)
CustomizationLimitedExtensive
Polymorphic SupportPartialFull
DependencyBuilt-in (.NET Core 3.0+)External NuGet Package

Using System.Text.Json

Basic Serialization and Deserialization

using System;
using System.Text.Json;

public class Person {
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program {
    static void Main() {
        var person = new Person { Name = "John Doe", Age = 30 };
        string json = JsonSerializer.Serialize(person);
        Console.WriteLine(json);

        Person deserializedPerson = JsonSerializer.Deserialize<Person>(json);
        Console.WriteLine(deserializedPerson.Name);
    }
}

Customizing Serialization with JsonSerializerOptions

System.Text.Json provides options to control serialization behavior:

var options = new JsonSerializerOptions {
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

Handling JSON Property Names with Attributes

using System.Text.Json.Serialization;

public class Product {
    [JsonPropertyName("product_name")]
    public string Name { get; set; }
    
    [JsonIgnore]
    public decimal InternalCost { get; set; }
}

Using Newtonsoft.Json

Basic Serialization and Deserialization

using Newtonsoft.Json;

var person = new Person { Name = "John Doe", Age = 30 };
string json = JsonConvert.SerializeObject(person, Formatting.Indented);
Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json);

Controlling Serialization with JsonSerializerSettings

var settings = new JsonSerializerSettings {
    Formatting = Formatting.Indented,
    NullValueHandling = NullValueHandling.Ignore,
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

Polymorphic Serialization

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum Status {
    Active,
    Inactive
}

Performance Optimizations

  • Use System.Text.Json for performance-sensitive applications

  • Use Streams for large JSON data

  • Avoid unnecessary serialization loops

  • Cache serialization settings for Newtonsoft.Json

Conclusion

Choosing the right serialization library and using best practices significantly impact performance and maintainability. For new .NET applications, System.Text.Json is preferred due to its performance advantages, while Newtonsoft.Json remains a great choice for advanced customization.

Understanding serialization techniques helps in building efficient, scalable applications, whether working with REST APIs, microservices, or data storage in C# applications.