How to Parse JSON in C#: System.Text.Json & Newtonsoft
Parse JSON in C# with System.Text.Json and Newtonsoft.Json: JsonSerializer.Deserialize into POCOs, JsonDocument for read-only DOM, options for case sensitivity, and how the two libraries differ.
Modern .NET ships JSON support in the box with System.Text.Json, the high-performance successor to the long-popular Newtonsoft.Json (Json.NET). For most new code, System.Text.Json is the right default. This guide covers deserializing JSON into C# classes, reading dynamic documents without a class, the options you will need for real-world APIs, and when Newtonsoft is still the better fit.
System.Text.Json: the built-in default
System.Text.Json is built into .NET Core and .NET 5+, so there is nothing to install. The general-purpose API is JsonSerializer, the equivalent of Newtonsoft's JsonConvert. To parse, define a class whose properties mirror the JSON, then call JsonSerializer.Deserialize: var person = JsonSerializer.Deserialize<Person>(json);. It also deserializes from streams and UTF-8 byte spans for efficiency.
Deserializing into a POCO
The typical pattern is a Plain Old CLR Object (POCO) with properties matching the JSON keys. By default, properties in the JSON that have no matching member are ignored, and deserialization fails if a property marked required is missing. Use the [JsonPropertyName] attribute when a JSON key does not match your C# naming, for example mapping user_name to a UserName property.
If you do not have a class yet, generate one from a sample with a JSON to C# tool so you skip the boilerplate of declaring every property.
// json holds: {"name":"Ada","age":36}
Person p = JsonSerializer.Deserialize<Person>(json);Case sensitivity and options
A common surprise: System.Text.Json is case-sensitive by default, so a JSON key name will not bind to a Name property unless you opt in. Pass JsonSerializerOptions with PropertyNameCaseInsensitive set to true to match regardless of case. The same options object controls enum handling, whether to allow comments and trailing commas (for JSONC-style input), null handling, and indented output when serializing.
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var p = JsonSerializer.Deserialize<Person>(json, options);Three APIs for three needs
- JsonSerializer — the general-purpose API that maps JSON to and from POCOs; use it for almost everything.
- JsonDocument — a read-only document object model for inspecting JSON you do not want to map to a class; navigate with RootElement and GetProperty.
- Utf8JsonReader — a low-level, forward-only reader for maximum performance and minimal allocation when you process tokens yourself.
Serializing back to JSON
JsonSerializer.Serialize(obj) produces a compact JSON string. For readable output, pass options with WriteIndented set to true. System.Text.Json adheres strictly to RFC 8259, so some defaults differ from Newtonsoft — notably stricter handling of comments, trailing commas, and quoted numbers — which is worth knowing when migrating.
When to use Newtonsoft.Json
Newtonsoft.Json remains excellent and is still the right choice for projects that depend on its broad feature set: advanced custom converters, LINQ-to-JSON (JObject/JArray), flexible default behaviors, and compatibility with older code. System.Text.Json has closed much of the gap and wins on performance and zero dependencies, so prefer it for new work and reach for Newtonsoft when you need a feature it does not yet cover.
Debugging payloads
When deserialization throws a JsonException, the message includes the path and position of the failure. Confirm the JSON is valid first by pasting it into a validator, and use a formatter to read nested structure. Fixing the data is usually faster than guessing which property mapping went wrong.
Frequently asked questions
Should I use System.Text.Json or Newtonsoft.Json?
Prefer System.Text.Json for new .NET code — it is built in, fast, and standards-compliant. Use Newtonsoft.Json when you need its richer feature set, such as advanced custom converters or LINQ-to-JSON, or for compatibility with existing code.
How do I deserialize JSON to an object in C#?
Define a class matching the JSON, then call var obj = JsonSerializer.Deserialize<MyClass>(jsonString) with System.Text.Json, or JsonConvert.DeserializeObject<MyClass>(jsonString) with Newtonsoft.
Why is my C# JSON deserialization returning null properties?
System.Text.Json is case-sensitive by default, so mismatched casing leaves properties unset. Pass JsonSerializerOptions with PropertyNameCaseInsensitive = true, or use [JsonPropertyName] attributes to map keys explicitly.
How do I read JSON without a class in C#?
Use JsonDocument.Parse(json) and navigate RootElement with GetProperty for a read-only DOM, or JsonNode for a mutable tree. Both let you read values without declaring a POCO.
Does System.Text.Json allow comments and trailing commas?
Not by default, because it follows RFC 8259 strictly. Enable them via JsonSerializerOptions by setting ReadCommentHandling and AllowTrailingCommas, which is useful for JSONC-style configuration files.
Related tools
Try these tools
JSON to C# Class Generator
Generate C# classes with JsonProperty attributes from JSON examples.
JSON Validator
Validate JSON instantly with precise, human-readable error messages and line numbers.
JSON Formatter & Beautifier
Format, prettify, and beautify messy JSON with configurable indentation and key sorting.
JSON Repair & Fix
Fix invalid JSON: trailing commas, quotes, unquoted keys, and LLM markdown fences.