DEV Community

mohamed Tayel
mohamed Tayel

Posted on

Serializing and Deserializing Records in C#

Records in C# provide a concise and immutable way to define data structures. Their built-in features make serialization and deserialization with System.Text.Json effortless. Whether you need a simple JSON representation or advanced customization, records offer great flexibility. This article dives into these features with multiple examples, covering common and advanced scenarios.


Serializing a Record to JSON

Serializing a record to JSON is straightforward. Let’s create a Student record and convert it into a JSON string:

using System.Text.Json;

public record Student(string Name, int Age);

class Program
{
    static void Main()
    {
        var student = new Student("Alice", 21);

        // Serialize the record to JSON
        string json = JsonSerializer.Serialize(student);

        Console.WriteLine(json);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

{"Name":"Alice","Age":21}
Enter fullscreen mode Exit fullscreen mode

Here, the JsonSerializer automatically maps the record properties to JSON key-value pairs.


Formatting JSON Output

To make the JSON output more readable, use the WriteIndented option:

var options = new JsonSerializerOptions { WriteIndented = true };
string indentedJson = JsonSerializer.Serialize(student, options);
Console.WriteLine(indentedJson);
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "Name": "Alice",
  "Age": 21
}
Enter fullscreen mode Exit fullscreen mode

Deserializing JSON into a Record

The Deserialize method maps JSON back into a record instance. Let’s reverse the process:

string jsonInput = "{\"Name\":\"Alice\",\"Age\":21}";

// Deserialize JSON to a Student record
var deserializedStudent = JsonSerializer.Deserialize<Student>(jsonInput);

Console.WriteLine(deserializedStudent);
Enter fullscreen mode Exit fullscreen mode

Output:

Student { Name = Alice, Age = 21 }
Enter fullscreen mode Exit fullscreen mode

Customizing JSON Property Names

Sometimes, you need to rename JSON properties for external APIs or readability. Use [JsonPropertyName] to customize property names.

Example: Renaming Properties

using System.Text.Json.Serialization;

public record Product(
    [property: JsonPropertyName("product_name")] string Name,
    [property: JsonPropertyName("product_cost")] decimal Price
);

class Program
{
    static void Main()
    {
        var product = new Product("Tablet", 600.00m);

        // Serialize with custom JSON property names
        string json = JsonSerializer.Serialize(product);
        Console.WriteLine(json);

        // Deserialize JSON back to Product
        string jsonInput = "{\"product_name\":\"Tablet\",\"product_cost\":600.0}";
        var deserializedProduct = JsonSerializer.Deserialize<Product>(jsonInput);
        Console.WriteLine(deserializedProduct);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Serialized JSON:

{"product_name":"Tablet","product_cost":600.0}
Enter fullscreen mode Exit fullscreen mode

Deserialized Record:

Product { Name = Tablet, Price = 600.0 }
Enter fullscreen mode Exit fullscreen mode

Ignoring Properties During Serialization

You can exclude specific properties using the [JsonIgnore] attribute. Let’s extend the Product record with a field we want to ignore.

Example: Ignoring a Property

public record Product(
    string Name,
    decimal Price,
    [property: JsonIgnore] string InternalCode
);

class Program
{
    static void Main()
    {
        var product = new Product("Phone", 1200.00m, "SECRET123");

        // Serialize to JSON
        string json = JsonSerializer.Serialize(product);
        Console.WriteLine(json);

        // Deserialize JSON back to Product
        string jsonInput = "{\"Name\":\"Phone\",\"Price\":1200.0}";
        var deserializedProduct = JsonSerializer.Deserialize<Product>(jsonInput);
        Console.WriteLine(deserializedProduct);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Serialized JSON:

{"Name":"Phone","Price":1200.0}
Enter fullscreen mode Exit fullscreen mode

Deserialized Record:

Product { Name = Phone, Price = 1200.0, InternalCode = }
Enter fullscreen mode Exit fullscreen mode

The InternalCode property is ignored during serialization but retains its default value when deserialized.


Advanced Scenarios

Ignoring Null Values

If you want to exclude null properties from JSON, use the DefaultIgnoreCondition option.

var options = new JsonSerializerOptions
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

var product = new Product("Tablet", 500.00m, null);
string json = JsonSerializer.Serialize(product, options);
Console.WriteLine(json);
Enter fullscreen mode Exit fullscreen mode

Output:

{"Name":"Tablet","Price":500.0}
Enter fullscreen mode Exit fullscreen mode

Nested Records and Serialization

Records can be nested, and JSON serialization handles this seamlessly.

public record Address(string Street, string City);
public record Customer(string Name, Address Address);

class Program
{
    static void Main()
    {
        var customer = new Customer("John", new Address("123 Main St", "Springfield"));

        // Serialize to JSON
        string json = JsonSerializer.Serialize(customer, new JsonSerializerOptions { WriteIndented = true });
        Console.WriteLine(json);

        // Deserialize JSON back to Customer
        string jsonInput = "{\"Name\":\"John\",\"Address\":{\"Street\":\"123 Main St\",\"City\":\"Springfield\"}}";
        var deserializedCustomer = JsonSerializer.Deserialize<Customer>(jsonInput);
        Console.WriteLine(deserializedCustomer);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Serialized JSON:

{
  "Name": "John",
  "Address": {
    "Street": "123 Main St",
    "City": "Springfield"
  }
}
Enter fullscreen mode Exit fullscreen mode

Deserialized Record:

Customer { Name = John, Address = Address { Street = 123 Main St, City = Springfield } }
Enter fullscreen mode Exit fullscreen mode

Handling Arrays in Records

Records with array or collection properties are fully supported. Let’s serialize a record with a list of orders:

public record Order(int Id, string Product, int Quantity);
public record OrderBatch(string Customer, List<Order> Orders);

class Program
{
    static void Main()
    {
        var batch = new OrderBatch(
            "Alice",
            new List<Order>
            {
                new Order(1, "Phone", 2),
                new Order(2, "Tablet", 1)
            }
        );

        // Serialize the order batch to JSON
        string json = JsonSerializer.Serialize(batch, new JsonSerializerOptions { WriteIndented = true });
        Console.WriteLine(json);

        // Deserialize JSON back to OrderBatch
        string jsonInput = "{\"Customer\":\"Alice\",\"Orders\":[{\"Id\":1,\"Product\":\"Phone\",\"Quantity\":2},{\"Id\":2,\"Product\":\"Tablet\",\"Quantity\":1}]}";
        var deserializedBatch = JsonSerializer.Deserialize<OrderBatch>(jsonInput);
        Console.WriteLine(deserializedBatch);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Serialized JSON:

{
  "Customer": "Alice",
  "Orders": [
    {
      "Id": 1,
      "Product": "Phone",
      "Quantity": 2
    },
    {
      "Id": 2,
      "Product": "Tablet",
      "Quantity": 1
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Deserialized Record:

OrderBatch { Customer = Alice, Orders = [Order { Id = 1, Product = Phone, Quantity = 2 }, Order { Id = 2, Product = Tablet, Quantity = 1 }] }
Enter fullscreen mode Exit fullscreen mode

Assignments

Easy Level

  1. Serialize a Person record with Name and Age into JSON and print it.
  2. Deserialize {"Name":"Jane","Age":30} into a Person record.

Medium Level

  1. Add a [JsonPropertyName] attribute to the Person record to rename Name to full_name and Age to person_age.
  2. Add a PhoneNumber property to Person and use [JsonIgnore] to exclude it from serialization.

Difficult Level

  1. Create an Invoice record with:

    • InvoiceNumber (string), Amount (decimal), and DueDate (DateTime).
    • Use [JsonPropertyName] to rename all properties for JSON output.
    • Exclude DueDate from serialization using [JsonIgnore].
  2. Create a Company record with:

    • Name (string) and Employees (List).
    • Serialize and deserialize the Company record with nested Person records.

Conclusion

Serializing and deserializing records in C# is straightforward, and with attributes like [JsonPropertyName] and [JsonIgnore], you can fine-tune how records interact with JSON. By mastering these features, you can create flexible, JSON-ready data models for real-world applications.

Top comments (1)

Collapse
 
programmerraja profile image
Boopathi

This article provides a clear and concise explanation of serializing and deserializing records in C# with System.Text.Json. The examples are well-structured and easy to follow, making it a great resource for developers who are new to records or need a refresher on their JSON capabilities.