Parsing & Reading JSON
Overview
ParsedJsonDocument<T> is a lightweight, read-only representation of a JSON value that utilizes pooled memory to minimize garbage collector impact. It provides an efficient way to parse and navigate JSON documents with minimal allocations.
Built on top of Corvus.Text.Json, which is derived from System.Text.Json, ParsedJsonDocument<T> extends the functionality while maintaining a high degree of source compatibility with the familiar System.Text.Json.JsonElement API.
Key Features
- Memory Efficient: Uses pooled memory from
ArrayPool<byte>to reduce GC pressure - Read-Only: Provides immutable access to parsed JSON data
- Multiple Input Sources: Supports parsing from strings, byte arrays, streams, and sequences
- IDisposable: Must be disposed to return pooled memory
- System.Text.Json Compatible: Works with familiar
System.Text.Jsonpatterns
Comparison with System.Text.Json
ParsedJsonDocument<T> is based on System.Text.Json.JsonDocument but provides several enhancements:
| Feature | System.Text.Json (JsonDocument) |
Corvus.Text.Json (ParsedJsonDocument<T>) |
|---|---|---|
| Generic Support | Fixed to JsonElement |
Generic over IJsonElement<T> for extensibility |
| Property Access | Sequential search-based property lookup | Optionally uses a property map with O(1) performance for repeated access |
| Additional Types | Standard .NET types | Includes BigNumber, BigInteger, NodaTime types (LocalDate, OffsetTime, OffsetDate, OffsetDateTime, Period) |
| Mutability | Read-only | Read-only by default, with mutable variant (JsonElement.Mutable) available via JsonDocumentBuilder |
| UTF-8 Support | Good | Enhanced with direct UTF-8 property access methods |
When to Use ParsedJsonDocument
- ✅ When you need JSON schema support
- ✅ When you need mutability support
- ✅ When you want to create custom JSON element types
- ✅ When you need extended type support (BigInteger, BigNumber, NodaTime types)
Basic Usage
Parsing JSON from a String
using Corvus.Text.Json;
string json = """
{
"name": "John",
"age": 30
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
string name = root.GetProperty("name"u8).GetString();
int age = root.GetProperty("age"u8).GetInt32();
Console.WriteLine($"Name: {name}, Age: {age}");
Parsing JSON from UTF-8 Bytes
ReadOnlySpan<byte> utf8Json = """
{
"message": "Hello, World!"
}
"""u8;
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(utf8Json.ToArray().AsMemory());
JsonElement root = doc.RootElement;
string message = root.GetProperty("message"u8).GetString();
Console.WriteLine(message); // Output: Hello, World!
Parsing JSON from a Stream
using FileStream fileStream = File.OpenRead("data.json");
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(fileStream);
JsonElement root = doc.RootElement;
// Process the JSON data...
Async Stream Parsing
Asynchronous parsing is ideal for large files or network streams:
using FileStream fileStream = File.OpenRead("large-data.json");
using ParsedJsonDocument<JsonElement> doc = await ParsedJsonDocument<JsonElement>.ParseAsync(fileStream);
JsonElement root = doc.RootElement;
// Process the JSON data...
Parsing from Memory Stream
ReadOnlySpan<byte> utf8Json = """
{
"message": "Hello from stream"
}
"""u8;
using var stream = new MemoryStream(utf8Json.ToArray());
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(stream);
JsonElement root = doc.RootElement;
string message = root.GetProperty("message"u8).GetString();
Working with JSON Arrays
string json = """
[
1,
2,
3,
4,
5
]
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
// Using foreach with EnumerateArray()
foreach (JsonElement element in root.EnumerateArray())
{
int value = element.GetInt32();
Console.WriteLine(value);
}
// Or using indexed access
// Note that indexed access is *not* as efficient as enumeration.
int length = root.GetArrayLength();
for (int i = 0; i < length; i++)
{
int value = root[i].GetInt32();
Console.WriteLine(value);
}
Working with Nested Objects
string json = """
{
"person": {
"name": "Alice",
"address": {
"city": "Seattle",
"zip": "98101"
}
}
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
JsonElement person = root.GetProperty("person"u8);
JsonElement address = person.GetProperty("address"u8);
string name = person.GetProperty("name"u8).GetString();
string city = address.GetProperty("city"u8).GetString();
string zip = address.GetProperty("zip"u8).GetString();
Console.WriteLine($"{name} lives in {city}, {zip}");
Getting Strongly-Typed Values
JsonElement provides methods to extract strongly-typed values from JSON. This is similar to System.Text.Json, but with additional types supported.
Numeric Types
string json = """
{
"byteValue": 255,
"sbyteValue": -128,
"shortValue": -32768,
"ushortValue": 65535,
"intValue": -2147483648,
"uintValue": 4294967295,
"longValue": -9223372036854775808,
"ulongValue": 18446744073709551615,
"floatValue": 3.14159,
"doubleValue": 2.718281828459045,
"decimalValue": 79228162514264337593543950335
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
// Integer types
byte byteVal = root.GetProperty("byteValue"u8).GetByte();
sbyte sbyteVal = root.GetProperty("sbyteValue"u8).GetSByte();
short shortVal = root.GetProperty("shortValue"u8).GetInt16();
ushort ushortVal = root.GetProperty("ushortValue"u8).GetUInt16();
int intVal = root.GetProperty("intValue"u8).GetInt32();
uint uintVal = root.GetProperty("uintValue"u8).GetUInt32();
long longVal = root.GetProperty("longValue"u8).GetInt64();
ulong ulongVal = root.GetProperty("ulongValue"u8).GetUInt64();
// Floating-point types
float floatVal = root.GetProperty("floatValue"u8).GetSingle();
double doubleVal = root.GetProperty("doubleValue"u8).GetDouble();
decimal decimalVal = root.GetProperty("decimalValue"u8).GetDecimal();
Boolean Values
string json = """
{
"isActive": true,
"isDeleted": false
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
bool isActive = root.GetProperty("isActive"u8).GetBoolean();
bool isDeleted = root.GetProperty("isDeleted"u8).GetBoolean();
String Values
string json = """
{
"name": "John Doe",
"email": "john.doe@example.com",
"description": null
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
string? name = root.GetProperty("name"u8).GetString();
string? email = root.GetProperty("email"u8).GetString();
string? description = root.GetProperty("description"u8).GetString(); // Returns null
Date and Time Values
string json = """
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-02-28T14:45:30.123+05:00",
"timestamp": "2024-03-01T00:00:00-08:00"
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
// DateTime values
DateTime createdAt = root.GetProperty("createdAt"u8).GetDateTime();
// DateTimeOffset values (preserves timezone information)
DateTimeOffset updatedAt = root.GetProperty("updatedAt"u8).GetDateTimeOffset();
DateTimeOffset timestamp = root.GetProperty("timestamp"u8).GetDateTimeOffset();
Guid Values
string json = """
{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"sessionId": "12345678-1234-1234-1234-123456789012"
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
Guid userId = root.GetProperty("userId"u8).GetGuid();
Guid sessionId = root.GetProperty("sessionId"u8).GetGuid();
Binary Data (Base64)
string json = """
{
"data": "SGVsbG8gV29ybGQh",
"signature": "AQIDBA=="
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
// Decode base64 strings to byte arrays
byte[] data = root.GetProperty("data"u8).GetBytesFromBase64();
byte[] signature = root.GetProperty("signature"u8).GetBytesFromBase64();
// data contains: "Hello World!" as bytes
// signature contains: [1, 2, 3, 4]
Extended Numeric Types (Beyond System.Text.Json)
Corvus.Text.Json provides additional numeric types not available in System.Text.Json:
Console.WriteLine("--- Example 12: Extended Numeric Types (Beyond System.Text.Json) ---");
string json = """
{
"largeInteger": 12345678901234567890,
"preciseNumber": 1234567890123456789.1234567890123456789,
"bigNumberWithScale": 123456789012345678901234567890123456789E-10
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
// BigInteger for large integers beyond long range
BigInteger largeNum = root.GetProperty("largeInteger"u8).GetBigInteger();
// BigNumber for high-precision arithmetic
BigNumber preciseNum = root.GetProperty("preciseNumber"u8).GetBigNumber();
BigNumber bigNumWithScale = root.GetProperty("bigNumberWithScale"u8).GetBigNumber();
NodaTime Types
For applications using NodaTime, Corvus.Text.Json provides direct support:
using NodaTime;
string json = """
{
"localDate": "2024-02-28",
"offsetTime": "14:30:00+05:00",
"offsetDate": "2024-02-28+00:00",
"offsetDateTime": "2024-02-28T14:30:00+05:00",
"period": "P1Y2M3DT4H5M6S"
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
LocalDate localDate = root.GetProperty("localDate"u8).GetLocalDate();
OffsetTime offsetTime = root.GetProperty("offsetTime"u8).GetOffsetTime();
OffsetDate offsetDate = root.GetProperty("offsetDate"u8).GetOffsetDate();
OffsetDateTime offsetDateTime = root.GetProperty("offsetDateTime"u8).GetOffsetDateTime();
Period period = root.GetProperty("period"u8).GetPeriod();
Type Checking and Safe Conversion
Always check the ValueKind before calling Get methods to avoid exceptions:
string json = """
{
"maybeNumber": "not a number",
"actualNumber": 42
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
JsonElement maybeNumber = root.GetProperty("maybeNumber"u8);
if (maybeNumber.ValueKind == JsonValueKind.Number)
{
int value = maybeNumber.GetInt32(); // Safe
}
else
{
Console.WriteLine("Not a number!"); // This will execute
}
// Use TryGet methods for safer conversion
if (root.GetProperty("actualNumber"u8).TryGetInt32(out int actualValue))
{
Console.WriteLine($"Value: {actualValue}"); // This will execute
}
Enumerating Object Properties
string json = """
{
"first": "John",
"last": "Smith",
"age": 30
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
JsonElement root = doc.RootElement;
foreach (JsonProperty<JsonElement> property in root.EnumerateObject())
{
Console.WriteLine($"{property.Name}: {property.Value}");
}
Parsing with Options
var options = new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip,
MaxDepth = 64
};
string json = """
{
"name": "John", /* comment */
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json, options);
JsonElement root = doc.RootElement;
// Process the JSON data...
Writing JSON from ParsedJsonDocument
After parsing a JSON document, you often need to serialize it for storage, transmission, or API responses. The WriteTo method provides efficient UTF-8 serialization.
Basic Serialization to Stream
string json = """
{
"message": "Hello",
"status": 200
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
// Write to any stream - file, network, memory
using var stream = new MemoryStream();
using (var writer = new Utf8JsonWriter(
stream,
new JsonWriterOptions { Indented = true }))
{
doc.WriteTo(writer);
}
string outputJson = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(outputJson);
Serialization Options
Control output formatting with JsonWriterOptions:
using System.Text.Encodings.Web;
string json = """{"name":"<script>alert('xss')</script>"}""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
var options = new JsonWriterOptions
{
Indented = true, // Pretty-print with indentation
SkipValidation = false, // Validate during write
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping // Less aggressive escaping
};
using var stream = new MemoryStream();
using (var writer = new Utf8JsonWriter(stream, options))
{
doc.WriteTo(writer);
}
string output = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(output);
Writing to File
string json = """
{
"config": "data",
"version": "1.0"
}
""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
using FileStream fileStream = File.Create("output.json");
using var writer = new Utf8JsonWriter(
fileStream,
new JsonWriterOptions { Indented = true });
doc.WriteTo(writer);
// Flush happens automatically on dispose
Writing to HTTP Response (ASP.NET Core)
For web APIs, write directly to the response stream for optimal performance:
public async Task WriteJsonResponse(HttpContext context)
{
// Parse or build your JSON document
string json = GetDataAsJson();
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
context.Response.ContentType = "application/json";
// Write directly to response body
await using var writer = new Utf8JsonWriter(
context.Response.Body,
new JsonWriterOptions { Indented = false });
doc.WriteTo(writer);
await writer.FlushAsync();
}
Getting JSON as String
For simpler scenarios, use ToString() or GetRawText():
string json = """{"message":"Hello","value":42}""";
using ParsedJsonDocument<JsonElement> doc = ParsedJsonDocument<JsonElement>.Parse(json);
// Get formatted string representation
string formattedJson = doc.RootElement.ToString();
Console.WriteLine(formattedJson);
// Get original raw JSON text (preserves formatting)
string rawJson = doc.RootElement.GetRawText();
Console.WriteLine(rawJson);
Note: ToString() creates a new string allocation. For high-performance scenarios, prefer WriteTo() with a writer.
Performance Considerations
- Use UTF-8 directly:
WriteTo()writes UTF-8 bytes without encoding conversion - Stream to destination: Write directly to your target stream instead of intermediate buffers
- Disable validation: Set
SkipValidation = trueif you trust the source data - Avoid ToString(): In hot paths, use
WriteTo()instead of string conversion - Reuse writers: For repeated operations, consider writer pooling (see JsonDocumentBuilder docs)
Performance Comparison
// ❌ Slower: Multiple allocations
string jsonString = doc.RootElement.ToString();
byte[] bytes = Encoding.UTF8.GetBytes(jsonString);
await stream.WriteAsync(bytes);
// ✅ Faster: Direct UTF-8 serialization
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false });
doc.WriteTo(writer);
await writer.FlushAsync();
Common Serialization Patterns
API Gateway: Parse and Forward
A common pattern in API gateways and middleware - parse incoming JSON, optionally validate or transform it, then forward to an upstream service:
public async Task ForwardJsonAsync(HttpContext context, string upstreamUrl)
{
// Parse incoming request
using var requestDoc = await ParsedJsonDocument<JsonElement>.ParseAsync(
context.Request.Body);
// Optional: validate or transform here
// if (!IsValid(requestDoc.RootElement)) { return BadRequest(); }
// Forward to upstream service
using var httpClient = new HttpClient();
using var stream = new MemoryStream();
using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false }))
{
requestDoc.WriteTo(writer);
}
stream.Position = 0;
var content = new StreamContent(stream);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await httpClient.PostAsync(upstreamUrl, content);
// Forward response back to client
context.Response.StatusCode = (int)response.StatusCode;
await response.Content.CopyToAsync(context.Response.Body);
}
Caching: Serialize for Storage
Serialize JSON documents to byte arrays for caching in Redis, Memcached, or in-memory caches:
public async Task CacheJsonAsync(string key, ParsedJsonDocument<JsonElement> doc)
{
using var stream = new MemoryStream();
using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = false }))
{
doc.WriteTo(writer);
}
byte[] jsonBytes = stream.ToArray();
// Store in cache with expiration
await _cache.SetAsync(
key,
jsonBytes,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
});
}
public async Task<ParsedJsonDocument<JsonElement>?> GetCachedJsonAsync(string key)
{
byte[]? jsonBytes = await _cache.GetAsync(key);
if (jsonBytes == null)
{
return null;
}
return ParsedJsonDocument<JsonElement>.Parse(jsonBytes.AsMemory());
}
Logging: Structured JSON
Log JSON data efficiently:
public void LogStructuredData(ParsedJsonDocument<JsonElement> data, string operation)
{
if (!_logger.IsEnabled(LogLevel.Information))
{
return;
}
// For logging, ToString() is fine - it's already a single allocation
_logger.LogInformation(
"Operation {Operation} completed with data: {Json}",
operation,
data.RootElement.ToString());
}
// For high-volume logging where you want to avoid ToString(),
// log the document directly and let the logger handle serialization:
public void LogStructuredDataHighVolume(ParsedJsonDocument<JsonElement> data, string operation)
{
if (!_logger.IsEnabled(LogLevel.Information))
{
return;
}
// Pass the JsonElement directly - many structured logging systems
// can serialize it without intermediate string conversion
_logger.LogInformation(
"Operation {Operation} completed with data: {@Data}",
operation,
data.RootElement);
}
File Operations: Batch Processing
Process multiple JSON files efficiently:
public async Task ProcessJsonFilesAsync(string inputDirectory, string outputDirectory)
{
foreach (string inputFile in Directory.GetFiles(inputDirectory, "*.json"))
{
// Parse with pooled memory
using FileStream inputStream = File.OpenRead(inputFile);
using ParsedJsonDocument<JsonElement> doc =
await ParsedJsonDocument<JsonElement>.ParseAsync(inputStream);
// Validate or transform
if (!ValidateDocument(doc.RootElement))
{
_logger.LogWarning("Skipping invalid file: {File}", inputFile);
continue;
}
// Write to output with formatting
string outputFile = Path.Combine(
outputDirectory,
Path.GetFileName(inputFile));
using FileStream outputStream = File.Create(outputFile);
using var writer = new Utf8JsonWriter(
outputStream,
new JsonWriterOptions { Indented = true });
doc.WriteTo(writer);
await writer.FlushAsync();
}
}
Comparison: ParsedJsonDocument vs System.Text.Json.JsonDocument
Writing/Serialization Comparison
Both support similar serialization patterns with identical APIs:
System.Text.Json.JsonDocument:
using System.Text.Json;
string json = """{"message":"Hello"}""";
using var doc = JsonDocument.Parse(json);
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
doc.WriteTo(writer);
string output = Encoding.UTF8.GetString(stream.ToArray());
Corvus.Text.Json.ParsedJsonDocument:
using Corvus.Text.Json;
string json = """{"message":"Hello"}""";
using var doc = ParsedJsonDocument<JsonElement>.Parse(json);
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
doc.WriteTo(writer);
string output = Encoding.UTF8.GetString(stream.ToArray());
Key Differences:
| Aspect | System.Text.Json.JsonDocument | Corvus.Text.Json.ParsedJsonDocument |
|---|---|---|
| API Compatibility | Standard .NET API | Compatible API with extensions |
| Type System | Fixed to JsonElement |
Generic over IJsonElement<T> |
When to Choose Which
Use System.Text.Json.JsonDocument when:
- Standard .NET library is sufficient
Use ParsedJsonDocument when:
- Need extended type support (BigNumber, NodaTime)
- Need JSON Schema Serialization support (
IJsonElement<T>)
Error Handling
Handling Write Errors
public async Task WriteJsonSafelyAsync(ParsedJsonDocument<JsonElement> doc, string filePath)
{
try
{
using var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
using var writer = new Utf8JsonWriter(
stream,
new JsonWriterOptions { Indented = true });
doc.WriteTo(writer);
await writer.FlushAsync();
_logger.LogInformation("Successfully wrote JSON to {FilePath}", filePath);
}
catch (IOException ex)
{
_logger.LogError(ex, "Failed to write JSON to file {FilePath}", filePath);
throw new ApplicationException($"Could not write to {filePath}", ex);
}
catch (UnauthorizedAccessException ex)
{
_logger.LogError(ex, "Access denied writing to {FilePath}", filePath);
throw;
}
}
Handling Parse and Write Pipeline
public async Task<bool> TryProcessJsonAsync(Stream input, Stream output)
{
ParsedJsonDocument<JsonElement>? doc = null;
try
{
// Parse
doc = await ParsedJsonDocument<JsonElement>.ParseAsync(input);
// Validate
if (!IsValidDocument(doc.RootElement))
{
_logger.LogWarning("Document failed validation");
return false;
}
// Write
using var writer = new Utf8JsonWriter(
output,
new JsonWriterOptions { Indented = false });
doc.WriteTo(writer);
await writer.FlushAsync();
return true;
}
catch (JsonException ex)
{
_logger.LogError(ex, "Invalid JSON format");
return false;
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error processing JSON");
return false;
}
finally
{
// Critical: Always dispose to return pooled memory
doc?.Dispose();
}
}
Important Notes
Memory Management
ParsedJsonDocument<T> uses pooled memory and must be disposed to return memory to the pool. Failure to dispose will result in increased GC pressure.
// ❌ Bad - memory leak
var doc = ParsedJsonDocument<JsonElement>.Parse(json);
// Missing dispose!
// ✅ Good - proper disposal
using var doc = ParsedJsonDocument<JsonElement>.Parse(json);
// Automatically disposed at end of scope
// ✅ Also good - explicit disposal
var doc = ParsedJsonDocument<JsonElement>.Parse(json);
try
{
// Use doc
}
finally
{
doc.Dispose();
}
Data Lifetime
When parsing from ReadOnlyMemory<byte> or ReadOnlySequence<byte>, the memory must remain valid for the entire lifetime of the document. The parser does not make a copy of the input data.
Thread Safety
While ParsedJsonDocument<T> itself is thread-safe for read operations after parsing, the underlying JSON data should not be modified during the document's lifetime.
Static Constants
For common literal values, use the static properties to avoid allocations:
JsonElement nullValue = ParsedJsonDocument<JsonElement>.Null;
JsonElement trueValue = ParsedJsonDocument<JsonElement>.True;
JsonElement falseValue = ParsedJsonDocument<JsonElement>.False;
Error Handling
try
{
string invalidJson = """
{
invalid json
}
""";
using var doc = ParsedJsonDocument<JsonElement>.Parse(invalidJson);
}
catch (JsonException ex)
{
Console.WriteLine($"Invalid JSON: {ex.Message}");
}
Performance Tips
- Use async for large streams: When parsing large files or network streams, use
ParseAsyncto avoid blocking - Reuse streams: When parsing multiple documents, reuse stream objects when possible
- Use UTF-8 directly: Parsing from
ReadOnlyMemory<byte>is more efficient than parsing from strings - Dispose properly: Always dispose documents to return memory to the pool