[C#] Converting Between Objects and JSON (System.Text.Json)

目次

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 JavaScriptEncoder to prevent escaping Japanese characters into \uXXXX format.
  • CamelCase: Automatically converts C# properties like Title to title in 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 title from JSON to the C# Title property during deserialization, set PropertyNameCaseInsensitive = 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 JsonException will occur. This must be handled by setting ReferenceHandler.Preserve.
  • Differences from Newtonsoft.Json: System.Text.Json behaves differently from the older Newtonsoft.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.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次