JSON to Dart

Generera Dart-klasser från JSON med fromJson och toJson

Prova ett exempel
Rotklassnamn:

JSON-inmatning

Dart-utdata

Körs lokalt · Säkert att klistra in hemligheter
Dart-klasser visas här…

Vad är JSON till Dart-konvertering?

JSON till Dart-konvertering tar ett råformat JSON-objekt och producerar Dart-klassdefinitioner med typade fält, en namngiven konstruktor, en fromJson-fabrik och en toJson-metod. Dart saknar körtidsreflektion i Flutter (dart:mirrors är inaktiverat), vilket innebär att du inte kan deserialisera JSON till typade objekt utan att skriva explicit mappningskod. Varje REST API-svar, Firebase-dokument eller konfigurationsnyttolast behöver en motsvarande Dart-modellklass innan du kan komma åt dess fält på ett typsäkert sätt.

En typisk Dart-modellklass för JSON deklarerar final-fält för varje nyckel, en konstruktor med namngivna parametrar (med nyckelordet required för icke-nullbara fält), en fabrikskonstruktor named fromJson som läser från en Map av String till dynamic, och en toJson-metod som returnerar en Map av String till dynamic. Nästlade JSON-objekt blir separata klasser. Arrayer blir typade List-fält. Nullbara JSON-värden använder Darts null-säkerhetssyntax med suffixet ? på typen.

Att skriva dessa modellklasser för hand innebär att du läser varje JSON-nyckel, bestämmer Dart-typen, skapar fromJson-castingen för varje fält (inklusive listmappning med .map().toList()), bygger en toJson-mappningsliteral och upprepar processen för varje nästlat objekt. För ett JSON-objekt med 12 fält och 2 nästlade objekt innebär det 3 klasser, 6 fabriksrader och dussintals cast-uttryck. En konverterare producerar allt detta på millisekunder från en enda inklistring.

Varför använda en JSON till Dart-konverterare?

Att manuellt skriva Dart-modellklasser från JSON innebär att läsa fältnamn, gissa typer från exempelvärden, skriva fromJson-casting med korrekt null-hantering och upprepa processen för nästlade objekt. När API-strukturen förändras berör varje fältuppdatering konstruktorn, fromJson och toJson. En konverterare tar bort det repetitiva arbetet.

Omedelbar klassgenerering
Klistra in JSON och få kompletta Dart-klasser med konstruktorer, fromJson-fabriker och toJson-metoder på under en sekund. Nästlade objekt och listor detekteras och mappas automatiskt.
🔒
Integritetsfokuserad hantering
Konverteringen körs helt i din webbläsare med JavaScript. Din JSON-data lämnar aldrig din maskin. API-nycklar, tokens och produktionsnyttolaster förblir privata.
📝
Null-säker utdata
Genererade klasser använder Darts sunda null-säkerhet. Nullbara JSON-fält får typsuffixet ? och utelämnar nyckelordet required i konstruktorer. Icke-nullbara fält markeras required.
📦
Inget konto eller installation
Öppna sidan och klistra in din JSON. Inget Dart SDK, inga pub-beroenden, inget konto. Fungerar på alla enheter med en webbläsare.

Användningsfall för JSON till Dart

Flutter-apputveckling
Generera modellklasser för REST API-svar som konsumeras av http- eller dio-paketen. Klistra in den JSON som ditt backend returnerar och få Dart-klasser klara för jsonDecode och widget-rendering.
Firebase/Firestore-integration
Skapa typade modellklasser för Firestore-dokumentsnapshots. Klistra in ett exempeldokument som JSON, generera Dart-klassen och använd fromJson med snapshot.data() i ditt repositorylager.
Tillståndshanteringsmodeller
Definiera typade tillståndsobjekt för Riverpod, Bloc eller Provider. Klistra in den förväntade tillståndsformen som JSON och få oföränderliga Dart-klasser med toJson för tillståndspersistens och hydration.
Generering av API-klientkod
Producera request- och response-modeller för Retrofit- eller Chopper-API-klienter. Klistra in JSON-exempelnyttolaster och få Dart-klasser som matchar dina OpenAPI-responsscheman.
Automatiserad testning
Bygg typade testfixtures från verkliga API-svar. Klistra in ett JSON-exempel, generera modellklassen och använd den direkt i enhets- och widget-tester utan att skriva fixture-strukturer för hand.
Lär dig Dart-mönster
Studenter som lär sig Flutter kan klistra in valfri JSON-struktur och se hur Dart representerar den: final-fält, namngivna konstruktorer, fromJson-fabriksmönster och null-säkerhetsannoteringar i praktiken.

Typmappningsreferens för JSON till Dart

Varje JSON-värde mappas till en specifik Dart-typ. Tabellen nedan visar hur konverteraren översätter varje JSON-typ. Kolumnen Alternativ visar typer som används i mindre vanliga eller manuella mappningsscenarier.

JSON-typExempelDart-typAlternativ
string"hello"StringString
number (integer)42intint
number (float)3.14doubledouble
booleantrueboolbool
nullnulldynamicNull / dynamic
object{"k": "v"}NestedClassMap<String, dynamic>
array of strings["a", "b"]List<String>List<String>
array of objects[{"id": 1}]List<Item>List<Item>
mixed array[1, "a"]List<dynamic>List<dynamic>

Serialiseringsmetoder för Dart JSON

Dart och Flutter erbjuder flera sätt att hantera JSON-serialisering. Manuell fromJson/toJson är det enklaste tillvägagångssättet och kräver ingen kodgenerering. För större projekt genererar build_runner-baserade lösningar som json_serializable och freezed mallkoden vid kompileringstid, vilket minskar fel och håller modellerna konsekventa med JSON-kontraktet.

TillvägagångssättBeskrivningKälla
json_serializableCode-generation-based JSON serialization. Generates .g.dart files at build time via build_runner. Type-safe and compile-time verified.Official (Google)
freezedGenerates immutable data classes with copyWith, fromJson/toJson, equality, and pattern matching support. Built on top of json_serializable.Community (rrousselGit)
built_valueGenerates immutable value types with serialization. Enforces immutability patterns. Used in larger codebases with strict data modeling.Google
dart_mappableAnnotation-based mapper that generates fromJson, toJson, copyWith, and equality. Simpler setup than freezed with similar features.Community
Manual fromJson/toJsonHand-written factory constructors and toJson methods. No code generation needed. Full control over the mapping logic.Built-in Dart

Manuell vs json_serializable vs freezed

Dart har tre vanliga metoder för JSON-modellklasser. Manuell fromJson/toJson har inga beroenden. json_serializable automatiserar mappningskoden. freezed lägger till oföränderlighet, copyWith och mönstermatchning ovanpå json_serializable.

Manual fromJson/toJson
Skriv fromJson-fabriker och toJson-metoder för hand. Inga beroenden, inget build_runner-steg. Du har full kontroll över castinglogiken och felhanteringen. Bäst för små projekt med ett fåtal modeller, eller när du behöver anpassad deserialisering som kodgeneratorer inte kan uttrycka. Detta är det utdataformat som det här verktyget genererar.
json_serializable
Annotera din klass med @JsonSerializable() och kör dart run build_runner build. Generatorn skapar en .g.dart-fil med _$ClassFromJson- och _$ClassToJson-funktioner. Hanterar @JsonKey för fältbyte av namn, standardvärden och anpassade konverterare. Standardvalet för medelstora till stora Flutter-projekt.
freezed
Annotera med @freezed och få oföränderliga klasser med fromJson, toJson, copyWith, likhet (== och hashCode) och toString genererade automatiskt. Stöder union-typer för förseglade klassmönster. Kräver både freezed och json_serializable som dev-beroenden. Bäst för tillståndshanteringsmodeller och komplexa domänobjekt.

Kodexempel

Dessa exempel visar hur man använder genererade Dart-klasser för JSON-deserialisering, hur man konfigurerar json_serializable med build_runner, och hur man genererar Dart-klasser programmatiskt från JavaScript och Python.

Dart (manual fromJson / toJson)
import 'dart:convert';

class User {
  final int id;
  final String name;
  final String email;
  final bool active;
  final Address address;
  final List<String> tags;

  User({
    required this.id,
    required this.name,
    required this.email,
    required this.active,
    required this.address,
    required this.tags,
  });

  factory User.fromJson(Map<String, dynamic> json) => User(
    id: json['id'] as int,
    name: json['name'] as String,
    email: json['email'] as String,
    active: json['active'] as bool,
    address: Address.fromJson(json['address'] as Map<String, dynamic>),
    tags: (json['tags'] as List<dynamic>).map((e) => e as String).toList(),
  );

  Map<String, dynamic> toJson() => {
    'id': id,
    'name': name,
    'email': email,
    'active': active,
    'address': address.toJson(),
    'tags': tags,
  };
}

class Address {
  final String street;
  final String city;
  final String zip;

  Address({required this.street, required this.city, required this.zip});

  factory Address.fromJson(Map<String, dynamic> json) => Address(
    street: json['street'] as String,
    city: json['city'] as String,
    zip: json['zip'] as String,
  );

  Map<String, dynamic> toJson() => {'street': street, 'city': city, 'zip': zip};
}

void main() {
  final jsonStr = '{"id":1,"name":"Alice","email":"alice@example.com","active":true,"address":{"street":"123 Main","city":"Springfield","zip":"12345"},"tags":["admin","user"]}';
  final user = User.fromJson(jsonDecode(jsonStr));
  print(user.name); // -> Alice
  print(jsonEncode(user.toJson())); // -> round-trip back to JSON
}
Dart (json_serializable + build_runner)
// pubspec.yaml dependencies:
//   json_annotation: ^4.8.0
//   dev_dependencies:
//     build_runner: ^2.4.0
//     json_serializable: ^6.7.0

import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart'; // generated by: dart run build_runner build

@JsonSerializable()
class User {
  final int id;
  final String name;
  final String email;
  @JsonKey(name: 'is_active')
  final bool isActive;
  final List<String> tags;

  User({
    required this.id,
    required this.name,
    required this.email,
    required this.isActive,
    required this.tags,
  });

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

// Run code generation:
// dart run build_runner build --delete-conflicting-outputs
JavaScript (generate Dart classes from JSON)
function jsonToDart(obj, name = "Root") {
  const classes = [];
  function infer(val, fieldName) {
    if (val === null) return "dynamic";
    if (typeof val === "string") return "String";
    if (typeof val === "number") return Number.isInteger(val) ? "int" : "double";
    if (typeof val === "boolean") return "bool";
    if (Array.isArray(val)) {
      const first = val.find(v => v !== null);
      if (!first) return "List<dynamic>";
      return `List<${infer(first, fieldName)}>`;
    }
    if (typeof val === "object") {
      const cls = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
      build(val, cls);
      return cls;
    }
    return "dynamic";
  }
  function build(obj, cls) {
    const fields = Object.entries(obj).map(([k, v]) =>
      `  final ${infer(v, k)} ${k};`
    );
    classes.push(`class ${cls} {\n${fields.join("\n")}\n}`);
  }
  build(obj, name);
  return classes.join("\n\n");
}

console.log(jsonToDart({ id: 1, name: "Alice", scores: [98, 85] }, "User"));
// class User {
//   final int id;
//   final String name;
//   final List<int> scores;
// }
Python (generate Dart model from JSON)
import json

def json_to_dart(obj: dict, class_name: str = "Root") -> str:
    classes = []

    def infer(val, name):
        if val is None:
            return "dynamic"
        if isinstance(val, bool):
            return "bool"
        if isinstance(val, int):
            return "int"
        if isinstance(val, float):
            return "double"
        if isinstance(val, str):
            return "String"
        if isinstance(val, list):
            if not val:
                return "List<dynamic>"
            return f"List<{infer(val[0], name)}>"
        if isinstance(val, dict):
            cls = name[0].upper() + name[1:]
            build(val, cls)
            return cls
        return "dynamic"

    def build(obj, cls):
        fields = [f"  final {infer(v, k)} {k};" for k, v in obj.items()]
        classes.append(f"class {cls} {{\n" + "\n".join(fields) + "\n}")

    build(obj, class_name)
    return "\n\n".join(classes)

data = json.loads('{"id": 1, "name": "Alice", "active": true}')
print(json_to_dart(data, "User"))
# class User {
#   final int id;
#   final String name;
#   final bool active;
# }

Vanliga frågor

Varför kan Flutter inte använda dart:mirrors för JSON-deserialisering?
Flutter inaktiverar dart:mirrors (reflektionsbiblioteket) eftersom trädgallring kräver att kompilatorn vid kompileringstid vet vilken kod som används. Reflektion skulle förhindra kompilatorn från att ta bort oanvända klasser, vilket ökar appens storlek. Det är därför Flutter-projekt behöver explicita fromJson/toJson-metoder eller kodgenerering istället för körtidsreflektion.
Ska jag använda json_serializable eller skriva fromJson för hand?
För projekt med färre än 10 modellklasser är handskriven fromJson/toJson okomplicerad och tillför inga byggberoenden. När du har fler än 10 modeller, eller modeller som förändras ofta, sparar json_serializable tid och minskar kopiera-klistra-fel. Det genererar mappningskoden från annoteringar, så att fälttillägg bara kräver att du kör om build_runner.
Hur hanterar konverteraren nästlade JSON-objekt?
Varje nästlat JSON-objekt blir en separat Dart-klass. Om ett JSON-fält med namnet "address" innehåller ett objekt med nycklarna "street" och "city" skapar konverteraren en Address-klass med dessa fält och typar föräldrafältet som Address. fromJson-fabriken kastar den nästlade mappningen och skickar den till Address.fromJson.
Vad händer när ett JSON-fält är null?
Null-fält typsätts som dynamic med suffixet ? eftersom konverteraren inte kan avgöra den avsedda typen från ett null-värde ensamt. Ersätt dynamic? med den korrekta typen (String?, int? osv.) när du känner till den från ditt API-kontrakt. Darts null-säkerhet kommer sedan att kontrollera korrekta null-kontroller vid kompileringstid.
Hur hanterar jag JSON-nycklar som inte är giltiga Dart-identifierare?
JSON-nycklar som "first-name" eller "2nd_place" är inte giltiga Dart-fältnamn. Med manuell fromJson kan du mappa vilken JSON-nyckel som helst till vilket Dart-fältnamn som helst i fabrikskonstruktorn. Med json_serializable använder du @JsonKey(name: 'first-name') för att annotera fältet. Konverteraren konverterar automatiskt nyckelnamn till camelCase Dart-fält.
Kan jag använda freezed med utdata från det här verktyget?
Verktyget genererar standard Dart-klasser med manuell fromJson/toJson. För att konvertera till freezed ändrar du klassen till att använda @freezed-annoteringen, tar bort den handskrivna konstruktorn och fabriken, och lägger till freezed-mixin. Kör sedan build_runner för att generera .freezed.dart- och .g.dart-filerna. Fältnamnen och typerna från den genererade utdatan överförs direkt.
Vad är skillnaden mellan en rå mappning och en typad Dart-klass för JSON?
En rå mappning (Map av String till dynamic) ger dig direkt åtkomst till JSON-data utan typkontroll. Du måste casta varje värde vid anropsplatsen, och stavfel i nyckelnamn misslyckas tyst vid körtid. En typad Dart-klass fångar typfelmatchningar vid fromJson-gränsen, ger IDE-autokomplettering för fältnamn och gör omstrukturering säker. Prestandaskillnaden är försumbar; fördelen handlar helt om korrekthet och underhållbarhet.