Conversor JSON para Dart

Gere classes Dart a partir de JSON com fromJson e toJson

Experimente um exemplo
Nome da classe raiz:

Entrada JSON

Saída Dart

Roda localmente · Seguro para colar segredos
As classes Dart aparecerão aqui…

O que é a conversão de JSON para Dart?

A conversão de JSON para Dart recebe um objeto JSON bruto e produz definições de classes Dart com campos tipados, um construtor nomeado, uma factory fromJson e um método toJson. O Dart não possui reflexão em tempo de execução no Flutter (dart:mirrors está desabilitado), portanto não é possível desserializar JSON em objetos tipados sem escrever código de mapeamento explícito. Toda resposta de REST API, documento Firebase ou payload de configuração precisa de uma classe de modelo Dart correspondente antes que você possa acessar seus campos com segurança de tipos.

Uma classe de modelo Dart típica para JSON declara campos final para cada chave, um construtor com parâmetros nomeados (usando a palavra-chave required para campos não anuláveis), um construtor factory chamado fromJson que lê de um Map de String para dynamic, e um método toJson que retorna um Map de String para dynamic. Objetos JSON aninhados se tornam classes separadas. Arrays se tornam campos List tipados. Valores JSON anuláveis usam a sintaxe de null safety do Dart com o sufixo ? no tipo.

Escrever essas classes de modelo à mão significa ler cada chave JSON, decidir o tipo Dart, criar o cast fromJson para cada campo (incluindo mapeamento de listas com .map().toList()), construir o literal de mapa toJson e repetir o processo para cada objeto aninhado. Para um objeto JSON com 12 campos e 2 objetos aninhados, isso significa 3 classes, 6 linhas de factory e dezenas de expressões de cast. Um conversor produz tudo isso em milissegundos a partir de um único cole.

Por que usar um conversor JSON para Dart?

Escrever classes de modelo Dart manualmente a partir de JSON envolve ler nomes de campos, deduzir tipos a partir de valores de exemplo, escrever casts fromJson com tratamento correto de nulos e repetir o processo para objetos aninhados. Quando o formato da API muda, cada atualização de campo toca o construtor, o fromJson e o toJson. Um conversor elimina esse trabalho repetitivo.

Geração instantânea de classes
Cole o JSON e obtenha classes Dart completas com construtores, factories fromJson e métodos toJson em menos de um segundo. Objetos aninhados e listas são detectados e mapeados automaticamente.
🔒
Processamento com privacidade
A conversão ocorre inteiramente no seu navegador usando JavaScript. Seus dados JSON nunca saem da sua máquina. Chaves de API, tokens e payloads de produção permanecem privados.
📝
Saída null-safe
As classes geradas usam o null safety robusto do Dart. Campos JSON anuláveis recebem o sufixo de tipo ? e omitem a palavra-chave required nos construtores. Campos não nulos são marcados como required.
📦
Sem instalação ou cadastro
Abra a página e cole o seu JSON. Sem Dart SDK, sem dependências pub, sem conta. Funciona em qualquer dispositivo com um navegador.

Casos de uso de JSON para Dart

Desenvolvimento de apps Flutter
Gere classes de modelo para respostas de REST API consumidas pelos pacotes http ou dio. Cole o JSON que o seu backend retorna e obtenha classes Dart prontas para jsonDecode e renderização de widgets.
Integração com Firebase / Firestore
Crie classes de modelo tipadas para snapshots de documentos do Firestore. Cole um documento de exemplo como JSON, gere a classe Dart e use fromJson com snapshot.data() na sua camada de repositório.
Modelos de gerenciamento de estado
Defina objetos de estado tipados para Riverpod, Bloc ou Provider. Cole o formato de estado esperado como JSON e obtenha classes Dart imutáveis com toJson para persistência e hidratação de estado.
Geração de código para clientes de API
Produza modelos de requisição e resposta para clientes de API Retrofit ou Chopper. Cole payloads JSON de exemplo e obtenha classes Dart que correspondem aos seus esquemas de resposta OpenAPI.
Testes automatizados
Construa fixtures de teste tipadas a partir de respostas reais de API. Cole uma amostra JSON, gere a classe de modelo e use-a diretamente em testes unitários e de widgets sem precisar escrever structs de fixture à mão.
Aprendizado de padrões Dart
Estudantes aprendendo Flutter podem colar qualquer estrutura JSON e ver como o Dart a representa: campos final, construtores nomeados, padrões factory fromJson e anotações de null safety na prática.

Mapeamento de tipos JSON para Dart

Cada valor JSON é mapeado para um tipo Dart específico. A tabela abaixo mostra como o conversor traduz cada tipo JSON. A coluna Alternativa mostra os tipos usados em cenários de mapeamento menos comuns ou manual.

Tipo JSONExemploTipo DartAlternativa
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>

Abordagens de serialização JSON em Dart

Dart e Flutter oferecem várias formas de lidar com serialização JSON. O fromJson/toJson manual é a abordagem mais simples e não requer geração de código. Para projetos maiores, soluções baseadas em build_runner como json_serializable e freezed geram o código repetitivo em tempo de compilação, reduzindo erros e mantendo os modelos consistentes com o contrato JSON.

AbordagemDescriçãoFonte
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

Manual vs json_serializable vs freezed

Dart tem três abordagens comuns para classes de modelo JSON. O fromJson/toJson manual tem zero dependências. json_serializable automatiza o código de mapeamento. freezed adiciona imutabilidade, copyWith e correspondência de padrões sobre o json_serializable.

Manual fromJson/toJson
Escreva factories fromJson e métodos toJson à mão. Zero dependências, sem etapa build_runner. Você tem controle total sobre a lógica de cast e o tratamento de erros. Ideal para projetos pequenos com poucos modelos, ou quando você precisa de desserialização personalizada que geradores de código não conseguem expressar. Este é o formato de saída que esta ferramenta gera.
json_serializable
Anote sua classe com @JsonSerializable() e execute dart run build_runner build. O gerador cria um arquivo .g.dart com as funções _$ClassFromJson e _$ClassToJson. Suporta @JsonKey para renomeação de campos, valores padrão e conversores personalizados. A escolha padrão para projetos Flutter de médio a grande porte.
freezed
Anote com @freezed e obtenha classes imutáveis com fromJson, toJson, copyWith, igualdade (== e hashCode) e toString gerados automaticamente. Suporta tipos union para padrões de classes seladas. Requer freezed e json_serializable como dependências de desenvolvimento. Ideal para modelos de gerenciamento de estado e objetos de domínio complexos.

Exemplos de código

Estes exemplos mostram como usar classes Dart geradas para desserialização de JSON, como configurar json_serializable com build_runner e como gerar classes Dart programaticamente a partir de JavaScript e 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;
# }

Perguntas frequentes

Por que o Flutter não pode usar dart:mirrors para desserialização JSON?
O Flutter desabilita dart:mirrors (a biblioteca de reflexão) porque o tree-shaking precisa saber em tempo de compilação qual código é usado. A reflexão impediria o compilador de remover classes não utilizadas, aumentando o tamanho do aplicativo. Por isso, projetos Flutter precisam de métodos fromJson/toJson explícitos ou geração de código em vez de reflexão em tempo de execução.
Devo usar json_serializable ou escrever fromJson à mão?
Para projetos com menos de 10 classes de modelo, fromJson/toJson escritos à mão são diretos e não adicionam dependências de build. Quando você tiver mais de 10 modelos, ou modelos que mudam frequentemente, json_serializable economiza tempo e reduz erros de copiar e colar. Ele gera o código de mapeamento a partir de anotações, então adições de campos exigem apenas re-executar o build_runner.
Como o conversor lida com objetos JSON aninhados?
Cada objeto JSON aninhado se torna uma classe Dart separada. Se um campo JSON chamado "address" contém um objeto com as chaves "street" e "city", o conversor cria uma classe Address com esses campos e tipifica o campo pai como Address. A factory fromJson faz o cast do mapa aninhado e o passa para Address.fromJson.
O que acontece quando um campo JSON é nulo?
Campos nulos são tipados como dynamic com o sufixo ? porque o conversor não consegue determinar o tipo pretendido apenas a partir de um valor nulo. Substitua dynamic? pelo tipo correto (String?, int?, etc.) quando souber o contrato da sua API. O null safety do Dart então vai impor as verificações corretas de nulo em tempo de compilação.
Como lidar com chaves JSON que não são identificadores Dart válidos?
Chaves JSON como "first-name" ou "2nd_place" não são nomes de campos Dart válidos. Com fromJson manual, você pode mapear qualquer chave JSON para qualquer nome de campo Dart no construtor factory. Com json_serializable, use @JsonKey(name: 'first-name') para anotar o campo. O conversor converte automaticamente os nomes das chaves para campos Dart em camelCase.
Posso usar freezed com a saída desta ferramenta?
A ferramenta gera classes Dart padrão com fromJson/toJson manual. Para converter para freezed, altere a classe para usar a anotação @freezed, remova o construtor e a factory escritos à mão e adicione o mixin freezed. Em seguida, execute build_runner para gerar os arquivos .freezed.dart e .g.dart. Os nomes e tipos dos campos da saída gerada são transferidos diretamente.
Qual é a diferença entre um mapa bruto e uma classe Dart tipada para JSON?
Um mapa bruto (Map de String para dynamic) dá acesso direto aos dados JSON sem verificação de tipos. Você precisa fazer o cast de cada valor no local de uso, e erros de digitação em nomes de chaves falham silenciosamente em tempo de execução. Uma classe Dart tipada detecta incompatibilidades de tipo na fronteira do fromJson, fornece autocompletar do IDE para nomes de campos e torna a refatoração segura. A diferença de desempenho é desprezível; o benefício é inteiramente sobre correção e manutenibilidade.