System.Text.Json
System.Text.Json is the modern JSON library in .NET — fast, allocation-aware, and source-generator-friendly. It replaces Newtonsoft.Json (Json.NET) for new code. Use JsonSerializerOptions to control casing, default values, and converters; use the source generator for AOT and lower allocations.
Serialise, deserialise, custom converters, source-gen
EXAMPLE
using System;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
class JsonDemo
{
// 1) Records serialise out of the box; use JsonPropertyName for renames
public record Order(
[property: JsonPropertyName("id")] string Id,
[property: JsonPropertyName("customer")] string Customer,
[property: JsonPropertyName("totalCents")] long TotalCents,
[property: JsonPropertyName("status")] OrderStatus Status,
[property: JsonPropertyName("paidAt")] DateTime? PaidAt
);
public enum OrderStatus { New, Paid, Shipped, Cancelled }
static readonly JsonSerializerOptions JsonOpts = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true,
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) },
};
static async Task Main()
{
var o = new Order("o1", "alice", 4995, OrderStatus.New, null);
// 2) Serialise to string
string s = JsonSerializer.Serialize(o, JsonOpts);
Console.WriteLine(s);
// 3) Deserialise back
var back = JsonSerializer.Deserialize<Order>(s, JsonOpts);
Console.WriteLine(back);
// 4) Stream straight into a file — no intermediate string allocation
await using (var fs = File.Create("order.json"))
await JsonSerializer.SerializeAsync(fs, o, JsonOpts);
await using (var rs = File.OpenRead("order.json"))
{
var fromFile = await JsonSerializer.DeserializeAsync<Order>(rs, JsonOpts);
Console.WriteLine(fromFile?.Id);
}
// 5) Source generator — zero reflection, lower allocations, AOT-safe
// 1. Define a partial context:
// [JsonSerializable(typeof(Order))]
// public partial class AppJsonContext : JsonSerializerContext {}
// 2. Use it:
// JsonSerializer.Serialize(o, AppJsonContext.Default.Order);
// JsonSerializer.Deserialize(s, AppJsonContext.Default.Order);
// 6) Polymorphic types via type discriminator (System.Text.Json 7+)
var payment = (PaymentEvent)new CardPayment("o1", "visa", 4995);
var json = JsonSerializer.Serialize(payment, JsonOpts);
Console.WriteLine(json); // { "kind": "card", "orderId": ..., "scheme": ..., "amount": ... }
var p2 = JsonSerializer.Deserialize<PaymentEvent>(json, JsonOpts);
Console.WriteLine(p2);
// 7) Custom converter — money as a single string field
var opts = new JsonSerializerOptions { Converters = { new MoneyConverter() } };
var receipt = new Receipt("r1", new Money(4995, "AUD"));
Console.WriteLine(JsonSerializer.Serialize(receipt, opts)); // { "id": "r1", "total": "AUD 49.95" }
}
}
[JsonPolymorphic(TypeDiscriminatorPropertyName = "kind")]
[JsonDerivedType(typeof(CardPayment), "card")]
[JsonDerivedType(typeof(BankTransfer), "bank")]
public abstract record PaymentEvent(string OrderId);
public record CardPayment(string OrderId, string Scheme, long Amount) : PaymentEvent(OrderId);
public record BankTransfer(string OrderId, string Bsb, long Amount) : PaymentEvent(OrderId);
public record Money(long Cents, string Currency);
public record Receipt(string Id, Money Total);
public class MoneyConverter : JsonConverter<Money>
{
public override Money Read(ref Utf8JsonReader reader, Type t, JsonSerializerOptions o)
{
var s = reader.GetString()!; // "AUD 49.95"
var parts = s.Split(' ');
var dollars = double.Parse(parts[1]);
return new Money((long)Math.Round(dollars * 100), parts[0]);
}
public override void Write(Utf8JsonWriter w, Money m, JsonSerializerOptions o)
=> w.WriteStringValue($"{m.Currency} {(m.Cents / 100.0):F2}");
}
Why it matters
For hot-path serialisation, generate context with [JsonSerializable] — the source generator skips reflection, allocates dramatically less, and works under AOT/trimming. It is the single change that turns System.Text.Json from "fast" to "as fast as any library I have benchmarked against".
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
using System.Text.Json;
string json = JsonSerializer.Serialize(new { Name = "Ada", Age = 36 });
var back = JsonSerializer.Deserialize<User>(json);
Try it Yourself »
Discussion
Loading…