JSON to C#

Convert JSON to C# classes or C# 9+ records instantly. Supports System.Text.Json, Newtonsoft attributes, nullable reference types, and nested types.

100% private · runs locally

Convert JSON to C# POCO classes or records instantly. All JSON keys are converted to PascalCase properties, correct .NET types are inferred (int, double, bool, List<T>), and serialization attributes are added for seamless System.Text.Json or Newtonsoft integration.

JSON input
C# output C#

JSON to C# Type Mapping Reference

When converting untyped JSON data into strongly-typed C# data transfer objects (DTOs), the generator analyzes each JSON token to select the most idiomatic .NET type. The table below outlines how primitive values, complex structures, and collections are mapped.

JSON Sample / Token Generated C# Type Nullable RTs Mode Mapping Rule & Serialization Note
"username": "ada" string string? Standard UTF-16 string mapping. With NRT enabled, marked nullable to prevent compiler warnings on omitted keys.
"age": 30 int int? Inferred via Number.isInteger(). For IDs larger than 2,147,483,647, consider replacing with long.
"score": 98.6 double double? Mapped to 64-bit IEEE double. For monetary or financial calculations, manually adjust to decimal in production.
"active": true bool bool? Native boolean literal mapping.
"notes": null object object? When a field has a null sample, the generator defaults to object as the fallback root type.
"tags": ["c#", "dotnet"] List<string> List<string>? Uniform primitive array mapped to generic List<T> using System.Collections.Generic.
"items": [{"id": 1}] List<Item> List<Item>? Object arrays trigger singularization of the key name (itemsItem) and extract a separate class.
"created_at": "2026-08-15T..." string string? ISO 8601 strings are output as raw string by default. Replace with DateTimeOffset for automatic time parsing.
"first-name": "Grace" FirstName FirstName? Keys with hyphens, underscores, or camelCase are normalized to PascalCase with a matching attribute mapping.

C# Classes vs. Positional Records for API Payloads

Modern .NET offers two primary paradigms for structuring DTOs: mutable class definitions with auto-properties, and immutable positional record declarations (available in C# 9+).

When to use Mutable Classes

  • Legacy framework compatibility (.NET Framework 4.8 or older ASP.NET Web API).
  • Bidirectional data-binding (WPF, Windows Forms, Blazor two-way bindings).
  • Entity Framework Core tracking models requiring parameterless constructors and mutable setters.
  • Complex inheritance hierarchies across multiple polymorphic data types.

When to use Positional Records

  • High-performance API ingestion and microservices pipelines.
  • Built-in structural value equality: two record instances with identical properties evaluate to true in unit test assertions.
  • Non-destructive mutation using C# with-expressions (var updated = item with { Price = 199.99 };).
  • Thread-safe data transfer across background worker services.

Below is a comparison of how the generator converts the same JSON payload into both forms:

Class Output (POCO)
using System.Text.Json.Serialization;

public class UserProfile
{
    [JsonPropertyName("user_id")]
    public int UserId { get; set; }

    [JsonPropertyName("email")]
    public string Email { get; set; }
}
Record Output (C# 9+)
using System.Text.Json.Serialization;

public record UserProfile(
    [property: JsonPropertyName("user_id")] int UserId,
    [property: JsonPropertyName("email")] string Email
);

Important note on record attributes: The generator prefixes record parameters with the [property: ...] target specifier. This ensures the compiler attaches the serialization attribute to the auto-generated property rather than only the constructor parameter.

System.Text.Json vs. Newtonsoft.Json (Json.NET)

Choosing the right attribute style depends on your project's target framework and serializer configuration. For an in-depth architectural breakdown and migration guide, read our dedicated article on System.Text.Json vs Newtonsoft.Json in modern .NET.

System.Text.Json (STJ)

Built directly into .NET Core 3.0+ and .NET 5+. Operates directly over UTF-8 byte spans without allocating intermediate strings, resulting in significantly lower memory allocation and higher throughput.

using System.Text.Json;

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
    WriteIndented = true
};

// Deserialization
var model = JsonSerializer.Deserialize<Root>(jsonString, options);

Newtonsoft.Json (Json.NET)

The historical standard in the .NET ecosystem. Features extensive flexibility, tolerant type coercion, support for legacy serialization callbacks, and JSONPath querying via JObject.SelectToken().

using Newtonsoft.Json;

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    Formatting = Formatting.Indented
};

// Deserialization
var model = JsonConvert.DeserializeObject<Root>(jsonString, settings);

Nullable Reference Types & The Sample Payload Trap

In C# 8 and later, projects with <Nullable>enable</Nullable> treat all reference types (string, arrays, class instances) as non-nullable by default. If a property is declared as public string Name { get; set; }, the C# compiler expects it to never be null.

The Sample Payload Trap: When you paste a sample JSON response into a generator, every field in that specific sample might contain a value. However, production APIs frequently omit optional fields, return null, or change shape during partial updates. If your generated C# model uses non-nullable types, deserializing a response where a key is missing will assign null to a non-nullable property, potentially causing unexpected NullReferenceException downstream.

Recommended practice: Enable the Nullable RTs toggle in the generator whenever working with external REST or GraphQL APIs. This appends ? to string and complex object types (string?, Category?), forcing calling code to handle possible null states safely.

Comparing jsonutils.app with Visual Studio & quicktype

Depending on your workflow, different JSON-to-C# conversion tools offer distinct trade-offs in speed, automation, and customization:

Feature / Tool jsonutils.app (This Tool) Visual Studio (Paste JSON as Classes) quicktype CLI / Web
Execution Context 100% In-Browser (Client-side) Integrated in Visual Studio IDE CLI (Node.js) or Web service
C# 9+ Records Support Yes (Positional syntax) No (Classes only) Yes (with CLI configuration)
Serializer Toggle System.Text.Json / Newtonsoft / None No attributes or legacy Newtonsoft Newtonsoft / System.Text.Json
Nullable Reference Types One-click toggle No Yes
Best Use Case Instant generation, VS Code, Rider, Mac/Linux dev Quick offline paste on Windows Visual Studio Automated CI/CD build-time code generation

If you work exclusively in Visual Studio on Windows, the built-in Edit > Paste Special > Paste JSON as Classes is very convenient for basic models. However, if you use JetBrains Rider, VS Code, Linux, or macOS, or if you need modern C# 9+ positional records with System.Text.Json attributes, jsonutils provides a faster and more customizable zero-install solution.

Related tools

Frequently asked questions

What is a C# POCO class?

POCO stands for Plain Old CLR Object — a simple C# class with no dependencies on framework-specific base classes. POCOs are used to represent data structures (like API response payloads) in a serializable, testable way. They typically contain auto-properties ({"{ get; set; }"}) and are decorated with JSON serialization attributes.

What is the difference between a C# class and a record?

Introduced in C# 9, records are reference types with value-based equality and built-in immutability. Use a class when you need mutable data or inheritance. Use a record for immutable data transfer objects (DTOs) — the compiler generates Equals, ToString, and with-expressions automatically.

When should I use [JsonPropertyName] vs [JsonProperty]?

Use [JsonPropertyName] from System.Text.Json.Serialization if you're on .NET 5+ (the built-in serializer). Use [JsonProperty] from Newtonsoft.Json if your project uses the Newtonsoft NuGet package — still common in .NET Framework and older ASP.NET Core projects.

What are nullable reference types and when should I enable them?

Nullable reference types (NRTs, C# 8+) add compile-time null safety. With NRTs enabled, string cannot be null by default — you must explicitly use string? for nullable strings. Modern .NET projects enable NRTs by default in the .csproj file with {"enable"}.

How are JSON arrays handled in C#?

JSON arrays become List<T> properties. If the array contains objects, a new class is generated for the item type (named from the singular of the property key). Primitive arrays become List<string>, List<int>, etc.

How do I deserialize JSON into these C# classes?

With System.Text.Json: var obj = JsonSerializer.Deserialize<Root>(jsonString);. With Newtonsoft: var obj = JsonConvert.DeserializeObject<Root>(jsonString);. Both will map JSON keys to the matching property using the attribute you've configured.

How do I resolve "JsonException: The JSON value could not be converted to System.Int32"?

This occurs in System.Text.Json when a JSON payload provides numbers formatted as quoted strings (e.g. "age": "25") or floating-point numbers where an integer was expected. Configure JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString or change the C# property type to double or long.

Why does JsonSerializer.Deserialize return null properties when JSON keys use camelCase?

System.Text.Json is strictly case-sensitive by default. If your C# class uses PascalCase properties (FirstName) without [JsonPropertyName("firstName")] attributes, deserialization fails to bind the values. To fix this globally, set PropertyNameCaseInsensitive = true in your JsonSerializerOptions.

How do I deserialize a JSON array at the root into a C# collection?

When an API response returns a top-level array [{...}, {...}] instead of a single object, deserialize directly into a generic collection type: var items = JsonSerializer.Deserialize<List<Item>>(jsonString);. You do not need a root wrapper class in this scenario.