The options
- Classes or records
-
Classes get
{ get; set; }properties; records get{ get; init; }, so values are set once, when the JSON is read. - Collections
- Arrays become
List<T>orT[]. - Attributes
-
When a property's C# name differs from its JSON name (
first_namebecomesFirstName), it gets[JsonPropertyName("first_name")]for System.Text.Json or[JsonProperty("first_name")]for Newtonsoft.Json, so it reads and writes the original names. Choose None if you configure a naming policy instead. - Namespace
- A file-scoped namespace for the types, such as
MyApp.Models. - Nullable reference types
-
On, the file starts with
#nullable enable: references that can be null are marked?, and the others start out empty (an empty string, collection or object), so none is left null. Off, it starts with#nullable disable. - Root type name
- The name of the outermost type, or of each item when the JSON is an array.
How values become types
Nulls and missing properties
A property that is null in some objects, or missing from some, becomes nullable:
int?, and with nullable reference types on, string?. One that is only ever
null, or whose values are of different kinds, becomes object?.
Numbers
Whole numbers become int, or long past 32 bits. Past 64 bits they become
Int128 with System.Text.Json and BigInteger with Newtonsoft, the type each
one reads; past 128 bits, System.Text.Json reads them only as double, which rounds
them. Numbers with a fraction or an exponent become decimal, or
double when a value is beyond what a decimal holds.
Dates and GUIDs
ISO 8601 date-times with an offset (2026-10-18T12:00:00Z) become
DateTimeOffset, and without one DateTime; a place where only some carry an
offset becomes DateTimeOffset, with a note, and dates among date-times count as having
none. Dates alone (2026-10-18) become DateOnly, and GUIDs
Guid. A place is only typed that way when every value in it qualifies; otherwise it
stays a string.
Names
Property and type names are PascalCase and valid C#, whatever the JSON key. Objects found under the
same key with the same properties, of the same types, share one type; the items of an array are
named in the singular (orders gives Order). A name that would shadow a
common .NET type gets a suffix (string gives StringItem).
Requirements
The code needs C# 12 and .NET 8 or later, and Newtonsoft.Json 13.0.2 or later for
DateOnly. It is tested by compiling it with the .NET 10 SDK and reading the sample JSON
back with both serializers.
Questions
How do I read the JSON with these classes?
With System.Text.Json, JsonSerializer.Deserialize<Root>(json); with
Newtonsoft.Json, JsonConvert.DeserializeObject<Root>(json). When the JSON is an
array or a plain value, a comment at the top of the code says which type to read it as, such as
List<Root>.
Why is a property object??
Its values were all null, or of different kinds, so there was nothing to tell its type
from; an array that was always empty gives List<object?> for the same reason. The
notes under the code list each such place; a sample with a real value there gives a real type.
Is my JSON uploaded?
No. It is parsed and converted in your browser, and the page's security policy blocks every network request from its scripts.