JSON to C# Online

Paste JSON and get C# classes or positional records ready for JsonSerializer.Deserialize<T>() or JsonConvert.DeserializeObject<T>(). Properties are PascalCase, each one carries [JsonPropertyName] (System.Text.Json) or [JsonProperty] (Newtonsoft.Json) with the original key, and nullable reference types mark exactly which values can be missing or null.

The code is generated in your browser; the JSON is never uploaded. Every item in an array is read, so a key that only some items have becomes nullable, numbers are typed from how they are written (long, double, and ulong or decimal for values beyond long), and you can add a namespace and choose between classes and records.

InputPaste, type or drop a .json file
C#Root.cs
#nullable enable

using System.Collections.Generic;
using System.Text.Json.Serialization;

public class Root
{
    [JsonPropertyName("id")]
    public long Id { get; set; }

    [JsonPropertyName("name")]
    public string Name { get; set; } = "";

    [JsonPropertyName("email")]
    public string Email { get; set; } = "";

    [JsonPropertyName("avatar_url")]
    public string AvatarUrl { get; set; } = "";

    [JsonPropertyName("is_active")]
    public bool IsActive { get; set; }

    [JsonPropertyName("created_at")]
    public string CreatedAt { get; set; } = "";

    [JsonPropertyName("address")]
    public Address Address { get; set; } = new();

    [JsonPropertyName("posts")]
    public List<Post> Posts { get; set; } = new();

    [JsonPropertyName("settings")]
    public Settings Settings { get; set; } = new();

    [JsonPropertyName("metadata")]
    public object? Metadata { get; set; } // only null in the sample
}

public class Address
{
    [JsonPropertyName("street")]
    public string Street { get; set; } = "";

    [JsonPropertyName("city")]
    public string City { get; set; } = "";

    [JsonPropertyName("state")]
    public string State { get; set; } = "";

    [JsonPropertyName("zip")]
    public string Zip { get; set; } = "";

    [JsonPropertyName("country")]
    public string Country { get; set; } = "";
}

public class Post
{
    [JsonPropertyName("id")]
    public long Id { get; set; }

    [JsonPropertyName("title")]
    public string Title { get; set; } = "";

    [JsonPropertyName("body")]
    public string Body { get; set; } = "";

    [JsonPropertyName("published")]
    public bool Published { get; set; }

    [JsonPropertyName("tags")]
    public List<string> Tags { get; set; } = new();

    [JsonPropertyName("created_at")]
    public string CreatedAt { get; set; } = "";

    [JsonPropertyName("updated_at")]
    public string? UpdatedAt { get; set; }
}

public class Settings
{
    [JsonPropertyName("theme")]
    public string Theme { get; set; } = "";

    [JsonPropertyName("notifications")]
    public bool Notifications { get; set; }

    [JsonPropertyName("language")]
    public string Language { get; set; } = "";
}
Valid JSON4 types · 25 fieldsDepth 41.0 KB → 2.1 KBProcessed locally
Send output toText Diff Checker

How to use it

  1. Paste JSON into Input, open or drop a .json file, or load a sample; the C# updates as you type.
  2. Choose Class or Record, the serializer, an optional namespace and the root type name.
  3. Press Convert (⌘↵), then copy the code or download it as a .cs file.

Related tools

JSON to TypeScriptConvertJSON to JavaConvertJSON FormatterFormatAPI TesterWeb & API

Next: call the endpoint that returns this JSON with the API Tester, generate matching front-end types with JSON to TypeScript, or compare two generated versions in the Text Diff Checker.

What this tool does

The converter reads the whole document and builds one type per object shape, with the root type first. All the objects in an array are merged into one type; a key that is missing from some of them or null in some of them becomes nullable: long? or bool? for value types, and string? or Address? for reference types when Nullable reference types is on. With it on, the file starts with #nullable enable and non-nullable reference properties of a class get an initializer (= "" or = new()), so the code compiles without CS8618 warnings. With it off, the output is plain C# 7.3 with a block namespace, for older projects and .NET Framework. Whole numbers become long, numbers written with a decimal point or exponent become double, and a field that mixes them is double. Integers above long become ulong, larger ones decimal, and anything beyond decimal becomes JsonElement for System.Text.Json (which cannot read BigInteger) or BigInteger for Newtonsoft. Arrays become List<T>, values whose kind varies become object, and an object with no keys becomes Dictionary<string, object?>. Every property gets an explicit name attribute, because System.Text.Json matches names case-sensitively by default. A property is renamed with a Value suffix when it would clash with its own type's name (error CS0542) or with a member every object or record already has, such as ToString. For Newtonsoft records whose keys differ only in case (id and ID), each constructor parameter is named too, so Newtonsoft does not mix them up.

Example input and output

Classes for System.Text.Json (Root type: User, Namespace: MyApp.Models)
Input
{"id": 7, "name": "Ada", "email": null, "roles": ["admin"], "address": {"city": "London", "postcode": "N1"}}
Output
#nullable enable

using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace MyApp.Models;

public class User
{
    [JsonPropertyName("id")]
    public long Id { get; set; }

    [JsonPropertyName("name")]
    public string Name { get; set; } = "";

    [JsonPropertyName("email")]
    public object? Email { get; set; } // only null in the sample

    [JsonPropertyName("roles")]
    public List<string> Roles { get; set; } = new();

    [JsonPropertyName("address")]
    public Address Address { get; set; } = new();
}

public class Address
{
    [JsonPropertyName("city")]
    public string City { get; set; } = "";

    [JsonPropertyName("postcode")]
    public string Postcode { get; set; } = "";
}

email was only ever null, so its type is unknown; change object? to string? once you know what it holds.

Positional records for Newtonsoft.Json (Record, Root type: Order)
Input
{"order_id": "A-1042", "total": 42.5, "lines": [{"sku": "TSH-S", "qty": 1}]}
Output
#nullable enable

using System.Collections.Generic;
using Newtonsoft.Json;

public record Order(
    [property: JsonProperty("order_id")] string OrderId,
    [property: JsonProperty("total")] double Total,
    [property: JsonProperty("lines")] List<Line> Lines
);

public record Line(
    [property: JsonProperty("sku")] string Sku,
    [property: JsonProperty("qty")] long Qty
);

The property: target puts the attribute on the property the record generates, which both serializers read. Records need C# 9 and .NET 5 or later.

Large numbers and an empty array (Root type: Post)
Input
{"tweet_id": 1850000000000000000, "views": 18446744073709551615, "score": 0.97, "attachments": []}
Output
#nullable enable

using System.Collections.Generic;
using System.Text.Json.Serialization;

public class Post
{
    [JsonPropertyName("tweet_id")]
    public long TweetId { get; set; }

    [JsonPropertyName("views")]
    public ulong Views { get; set; } // exceeds long in the sample

    [JsonPropertyName("score")]
    public double Score { get; set; }

    [JsonPropertyName("attachments")]
    public List<object?> Attachments { get; set; } = new(); // only empty arrays in the sample: element type unknown
}

1850000000000000000 still fits in long. views is the largest ulong, so it needs ulong. The sample's only attachments array was empty, so convert again with a filled one to type its items.

Common errors and fixes

Every property is null or 0 after JsonSerializer.Deserialize, with no exception
System.Text.Json matches property names case-sensitively unless told otherwise, so a property named Name never sees the key name. The generated [JsonPropertyName] attributes fix this; for hand-written classes, set PropertyNameCaseInsensitive = true or use JsonSerializerDefaults.Web, as ASP.NET Core does.
JsonException: The JSON value could not be converted to System.Int64. Path: $.qty
The value is a decimal number such as 1.5, or a quoted number such as "3". Change the property to double, or allow quoted numbers with JsonNumberHandling.AllowReadingFromString on the options or as [JsonNumberHandling] on the property.
CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor
The project has nullable reference types enabled and a string or object property has no value. Generated classes avoid this with initializers; if you remove them, either make the property nullable (string?) or add the required modifier (C# 11).
CS0542: 'Address': member names cannot be the same as their enclosing type
A class contains a key with its own name, such as an address object with an address key. The generator renames the property to AddressValue and keeps [JsonPropertyName("address")], so the JSON still maps.
JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[...]'
Newtonsoft found an object where the type expects an array: the API returns an object in some responses and a list in others, or wraps the list in an envelope such as {"data": [...]}. Convert a sample of the real envelope, or type the property as object or JToken and check its shape in code.
The JSON value could not be converted to System.Numerics.BigInteger
System.Text.Json has no built-in BigInteger support. Integers beyond decimal's range (about 7.9 × 10^28) are therefore generated as JsonElement, which keeps the digits; call GetRawText() and parse it with BigInteger.Parse. Newtonsoft.Json reads BigInteger directly.

Common use cases

  • Creating DTOs for an ASP.NET Core controller or minimal API endpoint
  • Typing a third-party API response for HttpClient with GetFromJsonAsync<T>()
  • Generating Newtonsoft.Json models for an older .NET Framework project
  • Modelling configuration or message payloads as immutable records
  • Typing webhook payloads for Azure Functions or background workers

Privacy and security notes

  • Conversion happens in JavaScript inside this browser tab. Your JSON is not sent to DevPrix, logged or stored.
  • Values from the sample are used only to choose types; the generated C# contains your key names but no data.
  • Share copies a link that carries the JSON after the # in the URL. Browsers do not send that part to servers, but anyone with the link can read it, so avoid sharing links built from responses that contain personal data.

Frequently asked questions

System.Text.Json or Newtonsoft.Json?

System.Text.Json is built into .NET Core 3.0 and later, and ASP.NET Core uses it by default; choose it for new code. Choose Newtonsoft.Json for .NET Framework projects, or when you depend on its extra features, such as JObject, more forgiving parsing or reading BigInteger. Switching only changes the attribute and the using directive.

Class or record?

Classes with { get; set; } work with every serializer and framework version and can be changed after reading. Positional records (C# 9, .NET 5+) are immutable and compare by value, which suits messages and API responses. Both System.Text.Json and Newtonsoft.Json create them through their constructor.

What changes when I turn off Nullable reference types?

Reference types lose their ? (string instead of string?), #nullable enable and the initializers are left out, and the namespace uses braces instead of the file-scoped form, so the classes compile as C# 7.3 on .NET Framework. Value types still use long? and bool? for values that can be missing or null.

Why does every property have a name attribute, even when the name matches?

Because whether a name matches depends on the serializer's settings. System.Text.Json is case-sensitive by default, so Id does not match id, while ASP.NET Core uses camelCase and ignores case. With an explicit attribute on every property, the mapping is the same in every setup and survives renaming the property.

How should I type dates and money?

They stay string and double, because JSON has no date or decimal type. Change a timestamp to DateTimeOffset (or DateTime), which both serializers parse from ISO 8601, and a price to decimal, which both read without rounding.