Skip to main content

JSON to Dart Class — fromJson / toJson, null-safe, Flutter-ready

JSON to Dart / Flutter class — paste JSON, get final fields, camelCase names, factory fromJson, toJson, null-safe T?, nested classes, and optional @JsonSerializable codegen.

  • Runs locally
  • Category Developer & DevOps
  • Best for Formatting, validating, shrinking, or inspecting code-adjacent text.
Examples:
How types, null-safety & fromJson/toJson are inferred

Each JSON object becomes a Dart class with camelCase fields, a named constructor, and (by default) a hand-written factory X.fromJson(Map<String, dynamic>) plus Map<String, dynamic> toJson(). Nested objects lift into their own named classes (User.address → UserAddress) and fromJson recurses into them. When the Dart field name differs from the wire key (snake_case, kebab-case), fromJson/toJson read and write the ORIGINAL key, so the JSON round-trips. Integer numbers infer int; fractional numbers infer double; a number that is sometimes whole and sometimes fractional widens to num. Arrays of objects fold into ONE class — keys missing from some elements (or seen as null) become nullable T? and their constructor parameter drops the required keyword. A value that is only ever null types as dynamic. Switch on "json_serializable" to emit @JsonSerializable(), the part .g.dart directive, @JsonKey(name:) renames, and _$XFromJson / _$XToJson bridges for build_runner codegen. Turn off null-safety for legacy (pre-2.12) Dart.

What this tool does

Paste any JSON payload — a Dio response, a Firebase document, a Supabase row, a third-party REST body — and get back a clean set of Dart model classes ready to drop into a Flutter project. Each object becomes a class with `final` typed fields, a named constructor, a `factory ClassName.fromJson(Map<String, dynamic> json)`, and a `Map<String, dynamic> toJson()`. JSON keys are camelCased into valid Dart identifiers (`site_admin` becomes `siteAdmin`, `created-at` becomes `createdAt`), while `fromJson`/`toJson` keep reading and writing the original wire key, so the model round-trips without losing a field. Numbers split into `int` and `double`, and a value that is whole in one sample and fractional in another widens to `num` so both literals fit. Null-safety is on by default: a key missing from some array element, or seen as JSON `null`, becomes a nullable `T?` and its constructor parameter drops the `required` keyword; a value that is only ever null types as `dynamic`. Nested objects lift into their own named classes (`User.address` becomes `UserAddress`) and `fromJson` recurses into them; arrays of objects fold into ONE shared class instead of N near-duplicates, and lists of scalars become `List<T>.from(...)`. Prefer build_runner codegen? Flip on json_serializable and the tool emits `@JsonSerializable()`, the `part 'name.g.dart';` directive, `@JsonKey(name:)` for renamed keys, and `_$ClassFromJson` / `_$ClassToJson` bridges instead of a hand-written body. You can toggle `final` vs mutable fields, drop the JSON methods entirely for a plain data holder, and turn off null-safety for legacy (pre-2.12) Dart. Everything runs in your browser — the JSON you paste never leaves the tab. A clear bilingual parse error points at the line and column when the JSON is malformed, and the result lives in a shareable URL plus a one-click copy.

Tool details

Input
Text + Numbers + Structured content
The page exposes text boxes, numeric controls, file pickers, or structured inputs depending on the tool.
Output
Live result + Copy + Download
The result area focuses on usable output, with copy, download, or preview actions when supported.
Privacy
Browser-side processing
The main tool logic does not call an external API, so inputs normally stay in the current tab.
Save / share
Shareable URL state
Key settings are encoded in the URL so another person can reopen the same setup.
Performance budget
Initial JS <= 25 KB
No WASM budget is declared, keeping the tool quick to open on mobile.
Best fit
Developer & DevOps · Developer
Category and role tags drive related tools, internal links, and quick fit checks.

How to use

  1. 1. Input

    Paste or drop your content into the tool panel.

  2. 2. Process

    Click the button. All processing is local in your browser.

  3. 3. Copy / Download

    Copy the result or download to disk in one click.

How JSON to Dart Class fits into your work

Use it in the small gaps between coding, reviewing, debugging, and shipping.

Developer jobs

  • Formatting, validating, shrinking, or inspecting code-adjacent text.
  • Preparing snippets for documentation, tickets, commits, or handoff.
  • Checking a small payload quickly without switching tools.

Developer checks

  • Run irreversible transforms like minify or obfuscate on a copy.
  • Keep secrets out of pasted snippets unless the tool explicitly stays local.
  • Use your normal tests or linter before shipping transformed code.

Good next steps

These links move the current task into a more complete workflow.

  1. 1 JSON to Kotlin Data Class JSON to Kotlin data class — paste JSON, get val properties, camelCase fields, nullable T?, nested classes, and kotlinx.serialization @SerialName, Gson @SerializedName, or Moshi @Json annotations. Open
  2. 2 JSON to Java Class JSON to Java POJO, record, or Lombok @Data — paste JSON, get camelCase fields with getters/setters, Jackson @JsonProperty or Gson @SerializedName, nested classes, primitive vs boxed inference. Open
  3. 3 JSON to TypeScript Interface JSON to TypeScript interface — paste JSON, get clean interfaces with union types from arrays, optional vs required detection, root name customizable. Open

Real-world use cases

  • Model a Dio response without hand-writing fromJson

    You hit an endpoint with Dio and want a typed model instead of digging through `response.data['user']['profile']['avatar']` with stringly-typed keys. Paste one sample response, set the root class name, and copy the generated Dart. You get `final` fields, a `factory User.fromJson(Map<String, dynamic>)`, and `toJson()` for the request body — nested objects already lifted into their own classes and wired up. What used to be 15 minutes of typing `as String` casts becomes a paste-and-copy, and the camelCase rename happens automatically so `created_at` reads as `createdAt` in your widget tree while still serialising back to the wire key.

  • Generate json_serializable models for a build_runner project

    Your Flutter app already runs build_runner with json_serializable, and you just got a new payload from the backend team. Flip on the json_serializable option, paste the JSON, and the tool emits the `@JsonSerializable()` class, the `part 'user.g.dart';` directive, `@JsonKey(name: 'created_at')` for every renamed field, and the `_$UserFromJson` / `_$UserToJson` bridges. Drop the file in, run `dart run build_runner build`, and the generated code matches the conventions your codebase already uses — no second pass to add annotations by hand.

  • Turn a Firebase document into an immutable DTO

    Firestore hands you a `Map<String, dynamic>` with mixed types and optional fields. Paste a representative document and keep `final` on so the model is immutable — the Flutter-recommended default for state that flows through your widgets. Fields that some documents omit come out as nullable `T?`, which matches Firestore's reality where not every doc has every key, and the null-guarded fromJson (`json['x'] == null ? null : ...`) means a missing field won't throw at parse time.

  • Match a Supabase row to a strongly-typed class

    A Supabase select returns snake_case columns (`user_id`, `is_active`, `last_seen`). Paste a row and the tool camelCases the Dart field names (`userId`, `isActive`, `lastSeen`) while keeping `fromJson`/`toJson` bound to the original column names, so the model round-trips against the database without a custom converter. Numbers that are sometimes integer (a count) and sometimes decimal (an average) widen to `num`, so you don't get a runtime cast error the first time the column returns a float.

  • Stop runtime type errors from untyped Map access

    Reaching into `data['items'][0]['price']` works until the day the backend sends a string where you expected a number and your app crashes in production. Generate a real class with this tool, parse once through `fromJson`, and every downstream access is statically typed — the analyzer flags a mismatch at compile time instead of your users hitting a red screen. Arrays of objects fold into one class, so a list of 200 items still gives you exactly one typed element model to reason about.

Common pitfalls

  • Treating every number as int. JSON has one number type, so a field that is 0 in your sample but actually carries cents or an average will be inferred as int and silently truncate a later 4.5 to a cast error. This tool widens int/double unions to num — but if a field is only ever whole in your sample yet can hold decimals in production, change it to double or num by hand before shipping.

  • Forgetting build_runner in json_serializable mode. The @JsonSerializable() annotation, the part directive, and the _$ClassFromJson/_$ClassToJson references all need `dart run build_runner build` to generate the .g.dart file. Add json_annotation + json_serializable + build_runner to pubspec.yaml and run codegen — or leave json_serializable off for a self-contained file with hand-written methods.

  • Dropping the wire key when renaming. fromJson reads json['site_admin'] because that is the JSON key, even though the Dart field is siteAdmin. Change the map key to 'siteAdmin' too and deserialisation looks for a key the server never sends, leaving the field null. Keep the original key in fromJson/toJson (or @JsonKey(name:) in codegen mode).

Privacy

Your JSON never leaves this browser tab. Parsing and type inference use the browser's built-in JSON.parse; there is no network call and no analytics on the textarea content. The Share link encodes your input and the root class name into the URL so a result is reproducible — that means YOU decide when to share. If the payload is sensitive (internal IDs, customer data, prod responses), copy the generated Dart instead of sharing the link. Only your option choices (final, null-safety, json_serializable, fromJson/toJson) are stored in localStorage so your preferred style persists across visits.

FAQ

Tool combos

Folks in your role tend to reach for these alongside this tool.

Made by Toolora · 100% client-side · Updated 2026-06-13