C# Programming Tutorial 0/45 lessons ~6 min read Lesson 32

    JSON Handling

    JSON dominates web APIs.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    JSON dominates web APIs. System.Text.Json offers high performance, trim-friendly source generators, and tight ASP.NET Core integration. Master JsonSerializerOptions, custom converters, and JsonNode for dynamic parsing.

    Interviewers ask camelCase vs PascalCase, DateTime serialization ISO 8601, and deserializing partial or dynamic JSON from third-party APIs.

    The story

    A customer portal API exposes strongly typed IDs in JSON as standard GUID strings, even though internally they are wrapped in a CustomerId value object. A custom JsonConverter controls exactly how that type appears on the wire — preventing accidental serialization of internal fields and keeping API contracts stable.

    Understanding the topic

    Key concepts

    • JsonSerializer.Serialize/Deserialize generic API.
    • JsonDocument/JsonElement read-only DOM parse.
    • JsonNode mutable DOM (.NET 6+).
    • JsonConverter for custom types.
    • ReferenceHandler.IgnoreCycles for graphs.
    • Minimal APIs bind JSON automatically.

    Step-by-step explanation

    1. ASP.NET Core configures JSON options in Program.cs.
    2. PropertyNamingPolicy.CamelCase for API output.
    3. Converters handle Guid, enums, dates.
    4. JsonSerializerContext source gen for AOT.
    5. TryGetProperty on JsonElement for safe access.
    6. HttpClient GetFromJsonAsync extension deserializes.

    Practical code example

    Custom converter for strongly typed ID and HttpClient JSON GET:

    csharp
    namespace TechLearningPro.Json;
    public readonly record struct CustomerId(Guid Value)
    {
    public static CustomerId New() => new(Guid.NewGuid());
    }
    public sealed class CustomerIdConverter : JsonConverter<CustomerId>
    {
    public override CustomerId Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
    new(Guid.Parse(reader.GetString()!));
    public override void Write(Utf8JsonWriter writer, CustomerId value, JsonSerializerOptions options) =>
    writer.WriteStringValue(value.Value.ToString("D"));
    }
    // Register in Program.cs: options.JsonSerializerOptions.Converters.Add(new CustomerIdConverter());

    Line-by-line code explanation

    • readonly record struct CustomerId(Guid Value) wraps a GUID in a domain-friendly type.
    • CustomerId.New() => new(Guid.NewGuid()) factory method creates fresh IDs.
    • JsonConverter<CustomerId> is the base class for custom serialization logic.
    • Read(ref Utf8JsonReader reader, ...) controls deserialization from JSON tokens.
    • Guid.Parse(reader.GetString()!) parses the string token into a GUID.
    • new CustomerId(...) wraps the parsed GUID in the value object.
    • Write(Utf8JsonWriter writer, CustomerId value, ...) controls JSON output format.
    • writer.WriteStringValue(value.Value.ToString("D")) writes the canonical GUID string format.
    • options.JsonSerializerOptions.Converters.Add(...) registers the converter globally in ASP.NET Core.

    Key takeaway: Custom converters encapsulate serialization rules for value objects. Keeps domain types strong at API boundary.

    Real-world use

    Where you'll use this in production

    • Third-party REST API integration.
    • Webhook payload parsing with JsonDocument.
    • Configuration appsettings.json binding.
    • Redis cache JSON blobs.

    Best practices

    • Use ISO 8601 DateTimeOffset for timestamps.
    • Validate JSON schema at API boundary.
    • Prefer strongly typed DTOs over dynamic.
    • Configure naming policy globally once.
    • Use JsonIgnore on sensitive fields.

    Common mistakes

    • Case sensitivity mismatch property names.
    • Deserializing large JSON to JsonDocument without dispose.
    • Enum as string vs int mismatch clients.
    • Infinite loop serializing parent-child graphs.

    Advanced interview questions

    Q1BeginnerSystem.Text.Json vs Newtonsoft?
    STJ faster, built-in; Newtonsoft more features, legacy apps.
    Q2BeginnerParse JSON without full class?
    JsonDocument, JsonElement, or JsonNode.
    Q3IntermediateCustom converter when?
    Non-standard format, value objects, polymorphic types.
    Q4IntermediateIgnore reference cycles?
    ReferenceHandler.IgnoreCycles or DTO projection without backrefs.
    Q5AdvancedDeserialize polymorphic webhook events safely.
    Require type discriminator field; whitelist mapped types; reject unknown; no TypeNameHandling.All.

    Summary

    System.Text.Json powers ASP.NET Core JSON. Custom converters and options tailor serialization. JsonDocument/JsonNode for dynamic parsing. Strong DTOs beat dynamic at API boundaries. Next: delegates.

    Ready to mark this lesson complete?Track your journey across the entire course.