High‑performance streaming JSON serialization for .NET using IAsyncEnumerable<T>.
Ideal for large datasets, real‑time APIs, and memory‑efficient processing.
Supports modern streaming‑friendly JSON formats:
- NDJSON (
application/x-ndjson) - JSON Lines (
application/jsonl) - JSON Sequence (
application/json-seq)
Built on top of System.Text.Json with an AOT‑friendly, zero‑allocation, and layered design.
| Package | Description | AOT-safe? |
|---|---|---|
| Juner.Sequence | Core streaming serializer (no HTTP dependency) | ✔ Fully AOT-safe |
| Juner.Http.Sequence | HttpClient / HttpContent integration |
✔ Fully AOT-safe |
| Juner.AspNetCore.Sequence | ASP.NET Core streaming input/output | ✔ Minimal API only ✘ MVC formatters |
- ⚡ High‑performance streaming JSON
- 🔄 Full
IAsyncEnumerable<T>support - 🧩 Multiple streaming formats (NDJSON / JSON Lines / JSON Sequence)
- 🛡️ AOT‑friendly core (
JsonTypeInfo<T>‑based API; no reflection) - 🧼 Clean and layered architecture
- 🌐 HttpClient integration (
Juner.Http.Sequence) - 🌐 ASP.NET Core integration (
Juner.AspNetCore.Sequence)
Juner.Sequence streams IAsyncEnumerable<T> directly, so its performance reflects
enumeration cost + write cost, without hidden buffering.
Representative results for 100,000 items on .NET 10
(measured on a laptop-class CPU: Surface Book 3 / Intel Core i7‑1065G7):
| Method | Mean | Allocated |
|---|---|---|
| NDJSON Streaming | 102.3 ms | 13.4 MB |
| JSON Array (STJ) | 13.2 ms | 7.5 MB |
| Iterate (baseline) | 41.7 ms | 288 B |
- JSON array is fastest due to single-buffer writes
- NDJSON adds I/O overhead but scales predictably with enumeration
- Laptop / cloud CPUs show proportionally slower NDJSON throughput
- All runtimes (.NET 7 → 10) show consistent improvements
👉 Full benchmark results are available in benchmarks/BENCHMARKS.md
--
graph TD;
A[Juner.Sequence<br/>Core] --> B[Juner.Http.Sequence<br/>HTTP Integration];
A --> C[Juner.AspNetCore.Sequence<br/>ASP.NET Core];
Note: Juner.AspNetCore.Sequence does not depend on Juner.Http.Sequence.
Both integrate independently with the core serializer.
[JsonSerializable(typeof(MyType))]
public partial class MyJsonContext : JsonSerializerContext { }await SequenceSerializer.SerializeAsync(
stream,
source,
MyJsonContext.Default.MyType,
SequenceSerializerOptions.JsonLines,
cancellationToken);await foreach (var item in SequenceSerializer.DeserializeAsyncEnumerable(
stream,
MyJsonContext.Default.MyType,
SequenceSerializerOptions.JsonLines,
cancellationToken))
{
Console.WriteLine(item);
}var request = new HttpRequestMessage(HttpMethod.Post, url)
.WithNdJsonContent(source, MyJsonContext.Default.MyType);
var response = await httpClient.SendAsync(request);
await foreach (var item in response.Content.ReadJsonLinesAsyncEnumerable<MyType>(
MyJsonContext.Default.MyType))
{
Console.WriteLine(item);
}- No reflection
- Fully compatible with Native AOT
- Uses
JsonTypeInfo<T>
- Based on
JsonSerializerOptions - May require reflection
- Not guaranteed to be AOT-safe
| Format | Content-Type | Option |
|---|---|---|
| NDJSON | application/x-ndjson | JsonLines |
| JSON Lines | application/jsonl | JsonLines |
| JSON Sequence | application/json-seq | JsonSequence |
(JSON Array intentionally omitted — see Note below.)
Note on JSON Arrays
application/json(JSON arrays) is not a streaming format and is not supported by the core library.
However,Juner.AspNetCore.Sequenceaccepts and returns JSON arrays only for convenience,
and they are always handled as non‑streaming buffered JSON.
MIT License
See the LICENSE file for details.
- Repository: https://github.com/juner/Sequence