C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
207: Utf8JsonReader and Utf8JsonWriter
I've spent a lot of time reviewing performance-critical code, and there is one misconception that keeps popping up when developers move into the high-performance side of System.Text.Json: they think Utf8JsonReader and Utf8JsonWriter are just "faster versions" of the JsonSerializer that they can swap in with minimal effort.
The "Drop-in Replacement" Myth
If you think you can just replace JsonSerializer.Deserialize<T> with a reader and get the same result with less CPU usage, you're in for a surprise. The serializer is a high-level abstraction; it handles the mapping of JSON keys to class properties, manages object instantiation, and handles type conversion for you.
The Utf8JsonReader, however, is a low-level, forward-only, non-cached cursor. It doesn't know what a "User" object is. It only knows that it just encountered a StartObject, followed by a PropertyName, followed by a String. If you try to use it like a serializer, you'll find yourself writing a massive, fragile while loop with a dozen if statements just to populate a single POCO. It's not a replacement; it's a different tool entirely.
Manual Control for Maximum Throughput
So, why would you ever put yourself through that manual labor? Because Utf8JsonReader operates directly on ReadOnlySpan<byte>. It doesn't need to convert the JSON bytes into a C# string before processing them. This eliminates huge amounts of memory allocation.
Imagine you have a 100MB JSON log file containing thousands of telemetry entries, but you only need to find the ErrorCode of entries where Severity is "Critical". Using the serializer, you'd either have to load the whole thing into memory or use a stream that still creates thousands of temporary objects. With the reader, you just skip through the bytes until you hit the keys you care about.
// Here is the pattern you'll actually use
ReadOnlySpan<byte> jsonUtf8Bytes = ...; // Your JSON data
var reader = new Utf8JsonReader(jsonUtf8Bytes);
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName && reader.ValueTextEquals("ErrorCode"))
{
reader.Read(); // Move to the value
int code = reader.GetInt32();
Console.WriteLine($"Found error: {code}");
}
}
Notice the ValueTextEquals method. I love this method because it compares the UTF-8 bytes directly to the string literal without allocating a new string for the property name. It's a tiny detail that makes a massive difference when you're processing millions of tokens.
Writing Without the Overhead
The Utf8JsonWriter works on the opposite principle. Instead of taking a complex object and reflecting over its properties to decide what to write, you tell the writer exactly what to emit, byte by byte.
It is designed to write directly to a BufferWriter or a Stream. This means you can construct a JSON response for a web API without ever creating a temporary "ResponseDTO" object in memory. You just pipe the data directly to the network buffer.
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
writer.WriteStartObject();
writer.WriteString("status", "success");
writer.WriteNumber("timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds());
writer.WriteStartArray("data");
writer.WriteNumber(101);
writer.WriteNumber(202);
writer.WriteEndArray();
writer.WriteEndObject();
writer.Flush();
It feels verbose, I know. But by removing the reflection and the intermediate object allocations, you're removing the primary bottlenecks that cause Garbage Collection (GC) pauses in high-traffic applications. Use the serializer for 95% of your app, but when you hit that one hot path that's killing your latency, this is where you reach for the reader and writer.
📋 Practical Task
Filtering High-Temperature Sensor Logs with Utf8JsonReader
You are building a monitoring tool that processes a large stream of sensor data. The data comes as a JSON array of objects, each containing a "sensorId" (string) and a "temp" (double). To save memory, you must not deserialize the entire array into a List.
Your Task: Write a method that takes a ReadOnlySpan<byte> of JSON data and uses Utf8JsonReader to find and print only the sensorId of sensors where the temp is greater than 100.0.
Example Input:
[{"sensorId": "A1", "temp": 98.5}, {"sensorId": "B2", "temp": 105.2}, {"sensorId": "C3", "temp": 110.0}]
Expected Output:
B2
C3
Requirements:
- Use
Utf8JsonReaderto iterate through the tokens. - Use
ValueTextEqualsto check for property names. - Do not use
JsonSerializerorJsonDocument.
There are no comments for now.