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);
}
}
Output:
{"Name":"Alice","Age":21}
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);
Output:
{
"Name": "Alice",
"Age": 21
}
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);
Output:
Student { Name = Alice, Age = 21 }
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);
}
}
Output:
Serialized JSON:
{"product_name":"Tablet","product_cost":600.0}
Deserialized Record:
Product { Name = Tablet, Price = 600.0 }
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);
}
}
Output:
Serialized JSON:
{"Name":"Phone","Price":1200.0}
Deserialized Record:
Product { Name = Phone, Price = 1200.0, InternalCode = }
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);
Output:
{"Name":"Tablet","Price":500.0}
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);
}
}
Output:
Serialized JSON:
{
"Name": "John",
"Address": {
"Street": "123 Main St",
"City": "Springfield"
}
}
Deserialized Record:
Customer { Name = John, Address = Address { Street = 123 Main St, City = Springfield } }
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);
}
}
Output:
Serialized JSON:
{
"Customer": "Alice",
"Orders": [
{
"Id": 1,
"Product": "Phone",
"Quantity": 2
},
{
"Id": 2,
"Product": "Tablet",
"Quantity": 1
}
]
}
Deserialized Record:
OrderBatch { Customer = Alice, Orders = [Order { Id = 1, Product = Phone, Quantity = 2 }, Order { Id = 2, Product = Tablet, Quantity = 1 }] }
Assignments
Easy Level
- Serialize a
Person
record withName
andAge
into JSON and print it. - Deserialize
{"Name":"Jane","Age":30}
into aPerson
record.
Medium Level
- Add a
[JsonPropertyName]
attribute to thePerson
record to renameName
tofull_name
andAge
toperson_age
. - Add a
PhoneNumber
property toPerson
and use[JsonIgnore]
to exclude it from serialization.
Difficult Level
-
Create an
Invoice
record with:-
InvoiceNumber
(string),Amount
(decimal), andDueDate
(DateTime). - Use
[JsonPropertyName]
to rename all properties for JSON output. - Exclude
DueDate
from serialization using[JsonIgnore]
.
-
-
Create a
Company
record with:-
Name
(string) andEmployees
(List). - Serialize and deserialize the
Company
record with nestedPerson
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)
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.