Overview
This article explains how to use the standard .NET library System.Text.Json to convert C# objects into JSON strings (serialization) and vice versa (deserialization). It covers practical settings such as preventing Unicode escaping for Japanese characters, automatic camelCase conversion, and “Pretty Print” formatting.
Specifications (Input/Output)
- Input: C# data object (with properties containing Japanese characters).
- Output: Formatted JSON string and the restored object data from JSON.
- Prerequisites: .NET Core 3.1 or higher (recommend .NET 6.0 or higher). Uses standard libraries only.
Basic Usage
This is the simplest form of conversion. By default, property names are kept in PascalCase, and non-ASCII characters may be escaped.
var data = new { Name = "Data", Value = 100 };
// Object -> JSON
string json = JsonSerializer.Serialize(data);
// JSON -> Object
var result = JsonSerializer.Deserialize<ExpectedType>(json);
Full Code Example
The following code handles a “Book Data” scenario with these specific requirements:
- Japanese Support: Uses
JavaScriptEncoderto prevent escaping Japanese characters into\uXXXXformat. - CamelCase: Automatically converts C# properties like
Titletotitlein JSON. - Formatting: Enables indentation for readable JSON output.
- Exclusion: Uses attributes to prevent internal-only properties from being output to JSON.
using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Unicode;
public class Program
{
public static void Main()
{
// 1. Create data to be serialized
var book = new Book
{
Title = "C# Programming Introduction",
PublishDate = new DateTime(2025, 1, 15),
IsAvailable = true,
InternalCode = "SECRET_123" // This should be excluded from JSON
};
// 2. Serialization settings (Options)
var options = new JsonSerializerOptions
{
// Settings to output Japanese characters as-is without Unicode escaping
Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
// Convert property names to camelCase (e.g., Title -> title)
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
// Output JSON with indentation (Pretty Print)
WriteIndented = true
};
Console.WriteLine("--- 1. Serialization (Object -> JSON) ---");
// Execute conversion
string jsonString = JsonSerializer.Serialize(book, options);
Console.WriteLine(jsonString);
Console.WriteLine("\n--- 2. Deserialization (JSON -> Object) ---");
// Execute restoration
// Restores object data from the JSON string
Book? deserializedBook = JsonSerializer.Deserialize<Book>(jsonString, options);
if (deserializedBook != null)
{
Console.WriteLine($"Title: {deserializedBook.Title}");
Console.WriteLine($"Date : {deserializedBook.PublishDate:yyyy/MM/dd}");
Console.WriteLine($"Stock: {deserializedBook.IsAvailable}");
// Since [JsonIgnore] is used, it remains the default (null/default) during restoration
Console.WriteLine($"ID : {deserializedBook.InternalCode ?? "(null)"}");
}
}
}
// Data class definition
public class Book
{
public string Title { get; set; } = string.Empty;
public DateTime PublishDate { get; set; }
public bool IsAvailable { get; set; }
// Use the [JsonIgnore] attribute to ignore this during both serialization and deserialization
[JsonIgnore]
public string? InternalCode { get; set; }
}
Example Execution Result
--- 1. Serialization (Object -> JSON) ---
{
"title": "C# Programming Introduction",
"publishDate": "2025-01-15T00:00:00",
"isAvailable": true
}
--- 2. Deserialization (JSON -> Object) ---
Title: C# Programming Introduction
Date : 2025/01/15
Stock: True
ID : (null)
Customization Points
- Case Insensitivity: If you want to flexibly map
titlefrom JSON to the C#Titleproperty during deserialization, setPropertyNameCaseInsensitive = true. - Enums as Strings: To output Enums as names (e.g., “Red”) instead of numbers (e.g., 0), add
options.Converters.Add(new JsonStringEnumConverter()). - Performance Optimization: In .NET 6.0 and later, you can use “Source Generators” to generate serialization code at compile time for even better performance.
Important Notes
- Properties Only: By default, only public properties (with getters/setters) are serialized. Public fields are ignored unless you use the
[JsonInclude]attribute. - Circular References: If objects reference each other (e.g., Parent -> Child -> Parent), a
JsonExceptionwill occur. This must be handled by settingReferenceHandler.Preserve. - Differences from Newtonsoft.Json:
System.Text.Jsonbehaves differently from the olderNewtonsoft.Json (Json.NET)in several areas, such as default escaping rules and handling of private setters. Perform thorough testing when migrating.
Advanced Application
Asynchronous Writing to Files
When handling large amounts of data, you can improve memory efficiency by writing directly to a FileStream instead of expanding the entire string in memory.
// Writing directly to a file (Asynchronous)
using (FileStream fs = File.Create("book.json"))
{
await JsonSerializer.SerializeAsync(fs, book, options);
}
// Reading directly from a file (Asynchronous)
using (FileStream fs = File.OpenRead("book.json"))
{
Book? result = await JsonSerializer.DeserializeAsync<Book>(fs, options);
}
Conclusion
Use attributes like [JsonIgnore] to strictly control the data exposed through your API. System.Text.Json is the high-performance, recommended standard for .NET Core 3.0 and later. Configuring the Encoder for Japanese characters and PropertyNamingPolicy for Web API integration are essential steps for real-world development.
