Inicio › Herramientas para desarrolladores › JSON a clase Dart

JSON a clase Dart

Pega un objeto JSON o una respuesta de API y obtén clases de modelo Dart null-safe para Flutter: campos final, un constructor con nombre, fromJson y toJson, copyWith y una clase para cada objeto anidado. Elige Dart simple o anotaciones de json_serializable. Todo funciona en tu navegador.

Última actualización:

Tu JSON se analiza en local en esta pestaña y nunca se sube. Consejo: Ctrl + Intro genera el código.

Publicidad
Publicidad

Cómo usar JSON a clase Dart

  1. Pega tu JSON en el cuadro izquierdo o abre un archivo .json. Se carga un ejemplo para que veas la salida desde el principio.
  2. Ponle nombre a la clase raíz, por ejemplo User o ProductResponse.
  3. Elige el estilo de salida: Dart simple con fromJson/toJson escritos a mano, o anotaciones de json_serializable para build_runner.
  4. Ajusta las opciones: qué campos son anulables, el formato de los nombres de campo, campos final, constructor const, copyWith, toString y análisis de DateTime.
  5. Copia o descarga el archivo .dart en tu proyecto Flutter y llama a User.fromJson(jsonDecode(body)).

Ejemplo: de JSON a una clase de modelo Dart

Dado este JSON con claves snake_case, una fecha, un objeto anidado y una lista:

{ "id": 7, "full_name": "Ada", "price": 3.5, "created_at": "2024-05-01T09:30:00Z",
  "tags": ["a", "b"], "owner": { "id": 1, "email": null } }

la salida en Dart simple (aquí sin copyWith) queda así:

class Root {
  const Root({
    required this.id,
    required this.fullName,
    required this.price,
    required this.createdAt,
    required this.tags,
    required this.owner,
  });

  final int id;
  final String fullName;
  final double price;
  final DateTime createdAt;
  final List<String> tags;
  final Owner owner;

  factory Root.fromJson(Map<String, dynamic> json) {
    return Root(
      id: json['id'] as int,
      fullName: json['full_name'] as String,
      price: (json['price'] as num).toDouble(),
      createdAt: DateTime.parse(json['created_at'] as String),
      tags: (json['tags'] as List<dynamic>).cast<String>().toList(),
      owner: Owner.fromJson(json['owner'] as Map<String, dynamic>),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'full_name': fullName,
      'price': price,
      'created_at': createdAt.toIso8601String(),
      'tags': tags,
      'owner': owner.toJson(),
    };
  }
}

Cómo se corresponden los valores JSON con los tipos Dart

Valor JSONTipo DartExpresión fromJson
"text"Stringjson['k'] as String
42intjson['k'] as int
3.5 (o mezcla de 3 / 3.5)double(json['k'] as num).toDouble()
truebooljson['k'] as bool
"2024-05-01T09:30:00Z"DateTimeDateTime.parse(json['k'] as String)
"x" o nullString?json['k'] as String?
{ … }Una clase con nombreOwner.fromJson(json['k'] as Map<String, dynamic>)
[ { … } ]List<Item>.map((e) => Item.fromJson(…)).toList()
{}Map<String, dynamic>json['k'] as Map<String, dynamic>
Solo null, tipos mezcladosdynamicjson['k']

Configurar json_serializable

Si eliges el estilo json_serializable, añade los paquetes y ejecuta el generador de código una vez (o usa watch mientras desarrollas):

dart pub add json_annotation
dart pub add --dev json_serializable build_runner
dart run build_runner build --delete-conflicting-outputs
  • La línea part 'root.g.dart'; debe coincidir con el nombre de tu archivo Dart.
  • Las clases que contienen otras clases de modelo reciben @JsonSerializable(explicitToJson: true), para que los objetos anidados se conviertan con su propio toJson() en lugar de quedarse como instancias.
  • Los campos cuyo nombre en Dart es distinto de la clave JSON reciben @JsonKey(name: 'json_key').

Preguntas frecuentes

¿Cómo uso la clase generada con una respuesta HTTP?

Importa dart:convert, decodifica el cuerpo y pasa el mapa a la factory: final user = User.fromJson(jsonDecode(response.body) as Map<String, dynamic>). Para enviar datos, llama a jsonEncode(user.toJson()). Si el JSON es un array de nivel superior, convierte cada elemento con fromJson como se muestra en el comentario generado.

¿Qué campos pasan a ser anulables?

Por defecto, un campo recibe un tipo anulable (por ejemplo String?) cuando su valor es null en algún punto del ejemplo o cuando la clave falta en algunos elementos de un array. Todos los demás campos son no anulables y se marcan como required en el constructor. También puedes hacer anulables todos los campos, lo que es más seguro con API que pueden omitir claves.

¿Por qué los double se analizan con (value as num).toDouble()?

jsonDecode devuelve un int para un número escrito sin punto decimal, así que un precio de 3 llega como int aunque otros elementos tengan 3.5. Convertirlo con as double lanzaría un error, así que el generador convierte a num y luego usa toDouble(), que acepta ambos.

Dart simple o json_serializable: ¿cuál elijo?

Dart simple no necesita paquetes ni generación de código y es fácil de leer y depurar. json_serializable es popular en apps más grandes: escribe por ti el código de conversión en un archivo .g.dart. Con ese estilo, añade json_annotation a dependencies y json_serializable más build_runner a dev_dependencies, y luego ejecuta dart run build_runner build.

¿Cómo se convierten las claves JSON en nombres de campo Dart?

Las claves se convierten a lowerCamelCase, como recomienda Effective Dart, así que first_name pasa a ser firstName. La clave original se sigue usando dentro de fromJson y toJson (o en @JsonKey(name: ...)), de modo que el JSON se lee y se escribe sin cambios. Las palabras reservadas como class o default reciben un guion bajo al final.

¿Qué pasa con los valores que solo son null y con los tipos mezclados?

Si un valor siempre es null, o mezcla tipos como cadena y número, el campo se tipa como dynamic, porque Dart no puede deducir un tipo más preciso a partir del ejemplo. Los objetos vacíos se convierten en Map<String, dynamic>. Sustituye dynamic por el tipo real cuando lo conozcas.

¿Se envía mi JSON a un servidor?

No. El JSON se analiza y el código Dart se genera con JavaScript que se ejecuta en esta página, así que no se sube nada.

¿Se prueban todas las herramientas de FreeToolCabin para comprobar su calidad y precisión?

Sí. Cada herramienta del sitio pasa pruebas automáticas en navegadores reales para comprobar que el resultado es correcto y que no hay errores. Si encuentras un fallo o tienes una sugerencia, escríbenos a [email protected] y lo revisaremos.

Herramientas relacionadas

Ver todas las de Conversores de datos y formatos de archivo →