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-09-01 · median of 4 quiet runs · typical spread ±3.3% · 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.9 µs ±142 ns15.1 µs ±129 ns1.00×21.7 KB-11%
Stj_sourcegen12.3 µs ±100 ns10.0 µs ±79 ns0.66×21.4 KB-19%
Newtonsoft_json34.3 µs ±193 ns31.1 µs ±319 ns2.06×70.0 KB-10%
RATIO VS BASELINE — 100 · net10.0
Stj_reflection1.00×
Stj_sourcegen0.66×
Newtonsoft_json2.06×
RESULTS — 10000
methodnet9.0net10.0ratioallocatedΔ net10.0
Stj_reflection baseline2.11 ms ±17.3 µs1.90 ms ±14.0 µs1.00×2.13 MB-10%
Stj_sourcegen1.76 ms ±9.0 µs1.48 ms ±21.2 µs0.78×2.13 MB-16%
Newtonsoft_json4.28 ms ±66.1 µs3.94 ms ±61.9 µs2.07×5.80 MB-8%
RATIO VS BASELINE — 10000 · net10.0
Stj_reflection1.00×
Stj_sourcegen0.78×
Newtonsoft_json2.07×
SCALING · net10.0 · MEAN TIME BY INPUT SIZE (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
4.42 ms198.2 µs8.9 µs10010000
THE LEDGER · SAME WORKLOAD ACROSS RELEASES (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
38.7 µs18.5 µs8.9 µs10.0.201 · 08-22 v210.0.201 · 09-01 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 baseline36.8 µs ±223 ns34.1 µs ±264 ns1.00×42.5 KB-7%
Stj_sourcegen37.2 µs ±239 ns33.5 µs ±285 ns0.98×42.5 KB-10%
Newtonsoft_json58.3 µs ±291 ns51.8 µs ±418 ns1.52×96.1 KB-11%
RATIO VS BASELINE — 100 · net10.0
Stj_reflection1.00×
Stj_sourcegen0.98×
Newtonsoft_json1.52×
RESULTS — 10000
methodnet9.0net10.0ratioallocatedΔ net10.0
Stj_reflection baseline4.63 ms ±86.2 µs4.43 ms ±141.9 µs1.00×4.16 MB-4%
Stj_sourcegen4.60 ms ±119.2 µs4.39 ms ±134.4 µs0.99×4.16 MB-5%
Newtonsoft_json7.44 ms ±164.0 µs6.77 ms ±110.7 µs1.53×9.19 MB-9%
RATIO VS BASELINE — 10000 · net10.0
Stj_reflection1.00×
Stj_sourcegen0.99×
Newtonsoft_json1.53×
SCALING · net10.0 · MEAN TIME BY INPUT SIZE (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
7.59 ms476.4 µs29.9 µs10010000
THE LEDGER · SAME WORKLOAD ACROSS RELEASES (LOG)
Stj_reflectionStj_sourcegenNewtonsoft_json
61.4 µs42.9 µs29.9 µs10.0.201 · 08-22 v210.0.201 · 09-01 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