C# (or more precisely .NET libraries) does it using reflection. Attributes let you adjust the behaviour.
record User(string Name, DateOnly DoB);
[JsonSerializable(typeof(User))]
partial class SerializerContext: JsonSerializerContext;
...
var user = new User("John", new(1984, 1, 1));
var response = await http.PostAsJsonAsync(
url, user, SerializerContext.Default.User);