BENCHMARKS · SERIALIZATION

System.Text.Json (reflection and source-gen) vs Newtonsoft, both directions. Suite and raw reports: github.com/gdhami-net/dotnet-benchmarks.

Intel Core Ultra 9 285HX · Windows 11 · BenchmarkDotNet 0.15.8 · SDK 10.0.201 · 2026-08-22 · single run — not yet median-of-N · bars/tables: mean time, lower is better

SerializeOrders

Serialize the same order list three ways: reflection-based System.Text.Json, its source-generated twin, and Newtonsoft.Json.

TAKEAWAY Turn on the source generator: same API, same output, roughly a quarter faster and AOT-safe. Keep Newtonsoft only where its features (converters, LINQ-to-JSON) are actually used.
In this run: Stj_sourcegen is fastest — 1.5× faster than the baseline.
RESULTS — 100
methodnet9.0net10.0ratioallocatedΔ net10.0
Stj_reflection baseline16.1 µs ±156 ns15.2 µs ±857 ns1.00×21.7 KB-6%
Stj_sourcegen12.7 µs ±1.0 µs10.1 µs ±752 ns0.67×21.4 KB-20%
Newtonsoft_json33.2 µs ±269 ns30.6 µs ±382 ns2.02×70.0 KB-8%
RATIO VS BASELINE — 100 · net10.0
Stj_reflection
1.00×
Stj_sourcegen
0.67×
Newtonsoft_json
2.02×
RESULTS — 10000
methodnet9.0net10.0ratioallocatedΔ net10.0
Stj_reflection baseline2.18 ms ±26.0 µs1.95 ms ±41.0 µs1.00×2.18 MB-11%
Stj_sourcegen1.77 ms ±36.1 µs1.50 ms ±33.5 µs0.77×2.17 MB-15%
Newtonsoft_json4.30 ms ±114.6 µs3.88 ms ±52.2 µs1.99×5.80 MB-10%
RATIO VS BASELINE — 10000 · net10.0
Stj_reflection
1.00×
Stj_sourcegen
0.77×
Newtonsoft_json
1.99×
SCALING · net10.0 · MEAN TIME BY INPUT SIZE (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
4.36 ms198.0 µs9.0 µs10010000
THE LEDGER · SAME WORKLOAD ACROSS RELEASES (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
38.7 µs18.6 µs9.0 µs10.0.201 · 08-22 v210.0.201 · 08-22 v3
THE CODE BEING MEASURED
Stj_reflection — what this measures

System.Text.Json with reflection-driven metadata — the default most codebases run.

[Benchmark (Baseline)]
public string Stj_reflection()
=> JsonSerializer.Serialize(_orders);
Stj_sourcegen — what this measures

System.Text.Json with compile-time source-generated metadata — no runtime reflection.

[Benchmark]
public string Stj_sourcegen()
=> JsonSerializer.Serialize(_orders, OrderJsonContext.Default.ListOrder);
Newtonsoft_json — what this measures

Newtonsoft.Json — the library much of .NET migrated from.

[Benchmark]
public string Newtonsoft_json()
=> Newtonsoft.Json.JsonConvert.SerializeObject(_orders);

DeserializeOrders

Read the same JSON back: reflection vs source-generated System.Text.Json vs Newtonsoft.

TAKEAWAY Deserialization is where serializer choice hurts most - it runs on every request you receive. Source-gen System.Text.Json is the default to standardize on.
In this run: Stj_sourcegen is fastest — 1.0× faster than the baseline.
RESULTS — 100
methodnet9.0net10.0ratioallocatedΔ net10.0
Stj_reflection baseline35.8 µs ±144 ns34.9 µs ±1.4 µs1.00×42.5 KB-2%
Stj_sourcegen37.4 µs ±1.5 µs34.0 µs ±1.9 µs0.97×42.5 KB-9%
Newtonsoft_json59.1 µs ±3.0 µs52.0 µs ±2.8 µs1.49×96.1 KB-12%
RATIO VS BASELINE — 100 · net10.0
Stj_reflection
1.00×
Stj_sourcegen
0.97×
Newtonsoft_json
1.49×
RESULTS — 10000
methodnet9.0net10.0ratioallocatedΔ net10.0
Stj_reflection baseline4.89 ms ±406.0 µs4.31 ms ±262.0 µs1.00×4.16 MB-12%
Stj_sourcegen4.52 ms ±112.7 µs4.45 ms ±324.2 µs1.03×4.19 MB-2%
Newtonsoft_json7.47 ms ±412.7 µs6.57 ms ±244.1 µs1.52×9.19 MB-12%
RATIO VS BASELINE — 10000 · net10.0
Stj_reflection
1.00×
Stj_sourcegen
1.03×
Newtonsoft_json
1.52×
SCALING · net10.0 · MEAN TIME BY INPUT SIZE (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
7.37 ms472.6 µs30.3 µs10010000
THE LEDGER · SAME WORKLOAD ACROSS RELEASES (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
61.4 µs43.2 µs30.3 µs10.0.201 · 08-22 v210.0.201 · 08-22 v3
THE CODE BEING MEASURED
Stj_reflection — what this measures

System.Text.Json, reflection-driven metadata.

[Benchmark (Baseline)]
public List<Order>? Stj_reflection()
=> JsonSerializer.Deserialize<List<Order>>(_json);
Stj_sourcegen — what this measures

System.Text.Json, source-generated metadata.

[Benchmark]
public List<Order>? Stj_sourcegen()
=> JsonSerializer.Deserialize(_json, OrderJsonContext.Default.ListOrder);
Newtonsoft_json — what this measures

Newtonsoft.Json.

[Benchmark]
public List<Order>? Newtonsoft_json()
=> Newtonsoft.Json.JsonConvert.DeserializeObject<List<Order>>(_json);

speed vs allocation

Fast is one axis. What it costs the GC is the other.

Stj_reflectionStj_sourcegenNewtonsoft_jsonStj_reflectionStj_sourcegenNewtonsoft_json
mean time → (log)allocated → (log)Stj_reflectionStj_sourcegenNewtonsoft_jsonStj_reflectionStj_sourcegenNewtonsoft_json