Documentacion

Guía de Inicio Rápido

🚀 Cómo usar la herramienta:

  • Personaliza el nombre de la clase principal.
  • Pega un objeto JSON (quoted o unquoted).
  • Opcional: Usa Formatear para limpiar tu JSON.
  • Configura el modo de salida (one-page / separated) en el panel.

⚡ Después de generar el código:

  • Copia y pega el código en tú proyecto
  • Ejecuta el generador de código de freezed:
    flutter packages pub run build_runner build

Objetivo

El objetivo de esta herramienta es generar código a partir de una estructura de datos en formatoJSON. A partir del contenido proporcionado, el sistema produce modelos de datos inmutables con anotaciones freezed para proyectos desarrollados en Dart/Flutter. La herramienta realiza inferencia de tipos y construye la jerarquía de clases de manera automática, incluyendo el manejo de estructuras anidadas de forma recursiva.

Funcionalidades Clave

  • Inferencia de Tipos Inteligente:
    • Identificación automática de tipos primitivos: int, double, bool y String.
    • Soporte para listas de tipos primitivos (por ejemplo, List<String>).
    • Generación recursiva de submodelos para objetos anidados y colecciones de objetos (List<T>).
  • Modos de Salida:Permite generar la salida en un solo archivo one-page o en múltiples archivos, uno por clase separated, según la configuración seleccionada.
  • Manejo de Valores Nulos:Los campos con valores null se declaran como anulables (por ejemplo, String?) y se omite la anotación required. Además, se añade un comentario//! INFO: Verificar tipo para indicar la necesidad de revisión manual.
  • Formatos de Entrada:Acepta datos en formato JSON tanto con clavesquoted es decir con comillas, como sin comillas unquoted. En el caso de las claves sin comillas, el sistema las formatea automáticamente antes de la generación del código.

Ejemplo Simple

JSON de Entrada:

{
"id": 1,
"name": "Elias",
"profile": { "age": 27, "country": "Ecuador" }
}

Salida Dart:

import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
abstract class User with _$User {
const factory User({
required int id,
required String name,
required Profile profile,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
@freezed
abstract class Profile with _$Profile {
const factory Profile({
required int age,
required String country,
}) = _Profile;
factory Profile.fromJson(Map<String, dynamic> json) =>
_$ProfileFromJson(json);
}

Ejemplo Complejo (Recursividad)

JSON de Entrada (Anidado):

{
"username": "tellxmaster",
"firstName": "Elias",
"lastName": "Elias",
"address": {
"mainStreet": "Huigra",
"secondary": "Quichuas",
"reference": null,
"coords": {
"lat": 0.4,
"long": 0,
"geoDetails": {
"altitude": 2800,
"region": {
"country": "Ecuador",
"province": "Chimborazo",
"city": "Alausí",
"neighborhood": {
"name": "Centro Histórico",
"population": 3400,
"security": {
"level": "medium",
"patrols": ["night", "weekend"]
}
}
}
}
}
},
"phone": {
"mobile": "+593987654321",
"home": null,
"verified": true
},
"social": {
"email": "elias@example.com",
"links": {
"github": "https://github.com/tellxmaster",
"twitter": "@tellxmaster",
"website": "https://tellxmaster.dev"
}
},
"preferences": {
"theme": "dark",
"language": "es",
"notifications": {
"email": true,
"sms": false,
"push": {
"enabled": true,
"channels": ["system", "promotions", "security"]
}
}
},
"devices": [
{
"type": "laptop",
"brand": "Dell",
"os": {
"name": "Ubuntu",
"version": "24.04",
"kernel": {
"type": "Linux",
"build": "6.8.0-35-generic"
}
},
"network": {
"ip": "192.168.1.10",
"mac": "A4:B2: 1C: 3D: 9E:F2",
"connections": [
{
"ssid": "HomeWifi",
"strength": 85,
"encryption": "WPA2"
},
{
"ssid": "OfficeNet",
"strength": 70,
"encryption": "WPA3"
}
]
}
},
{
"type": "smartphone",
"brand": "Google",
"model": "Pixel 8",
"os": {
"name": "Android",
"version": "15",
"securityPatch": "2025-10-05"
},
"apps": [
{
"name": "Telegram",
"permissions": {
"camera": true,
"contacts": true,
"location": false
}
},
{
"name": "GitHub",
"permissions": {
"notifications": true,
"storage": false
}
}
]
}
],
"activity": {
"lastLogin": "2025-11-07T22: 45: 00Z",
"sessions": [
{
"device": "laptop",
"location": "Ecuador",
"ip": "192.168.1.10",
"timestamp": "2025-11-07T22: 40: 00Z"
},
{
"device": "smartphone",
"location": "Ecuador",
"ip": "192.168.1.12",
"timestamp": "2025-11-06T19: 30: 00Z"
}
],
"history": {
"logins": 152,
"actions": {
"codePushes": 340,
"issuesOpened": 58,
"comments": 902,
"repositories": {
"active": 12,
"archived": 5,
"details": [
{
"name": "AI-Playground",
"language": "Python",
"contributors": [
{
"name": "María",
"role": "Maintainer"
},
{
"name": "Elias",
"role": "Owner"
}
]
}
]
}
}
}
},
"meta": {
"createdAt": "2020-04-21T10: 00: 00Z",
"updatedAt": "2025-11-07T22: 45: 00Z",
"version": "2.5.1",
"tags": ["developer", "backend", "linux", "open-source"],
"status": {
"active": true,
"verified": true,
"roles": ["admin", "contributor"]
}
}
}

Salida Dart (Clase principal):

import 'package:freezed_annotation/freezed_annotation.dart';
part 'user_info.freezed.dart';
part 'user_info.g.dart';
@freezed
abstract classUserInfo with _$UserInfo {
const factory UserInfo({
required String username,
required String firstName,
required String lastName,
required Address address,
required Phone phone,
required Social social,
required Preferences preferences,
required List devices,
required Activity activity,
required Meta meta,
}) = _UserInfo;
factory UserInfo.fromJson(Map<String, dynamic> json) =>
_$UserInfoFromJson(json);
}
@freezed
abstract classAddress with _$Address {
const factory Address({
required String mainStreet,
required String secondary,
String? reference,
required Coords coords,
}) = _Address;
factory Address.fromJson(Map<String, dynamic> json) =>
_$AddressFromJson(json);
}
@freezed
abstract classCoords with _$Coords {
const factory Coords({
required double lat,
@JsonKey(name: 'long') required double lon,
required GeoDetails geoDetails,
}) = _Coords;
factory Coords.fromJson(Map<String, dynamic> json) =>
_$CoordsFromJson(json);
}
@freezed
abstract classGeoDetails with _$GeoDetails {
const factory GeoDetails({
required int altitude,
required Region region,
}) = _GeoDetails;
factory GeoDetails.fromJson(Map<String, dynamic> json) =>
_$GeoDetailsFromJson(json);
}
@freezed
abstract classRegion with _$Region {
const factory Region({
required String country,
required String province,
required String city,
required Neighborhood neighborhood,
}) = _Region;
factory Region.fromJson(Map<String, dynamic> json) =>
_$RegionFromJson(json);
}
@freezed
abstract classNeighborhood with _$Neighborhood {
const factory Neighborhood({
required String name,
required int population,
required Security security,
}) = _Neighborhood;
factory Neighborhood.fromJson(Map<String, dynamic> json) =>
_$NeighborhoodFromJson(json);
}
@freezed
abstract classSecurity with _$Security {
const factory Security({
required String level,
required List<String> patrols,
}) = _Security;
factory Security.fromJson(Map<String, dynamic> json) =>
_$SecurityFromJson(json);
}
@freezed
abstract classPhone with _$Phone {
const factory Phone({
String? mobile,
String? home,
required bool verified,
}) = _Phone;
factory Phone.fromJson(Map<String, dynamic> json) =>
_$PhoneFromJson(json);
}
@freezed
abstract classSocial with _$Social {
const factory Social({
required String email,
required Links links,
}) = _Social;
factory Social.fromJson(Map<String, dynamic> json) =>
_$SocialFromJson(json);
}
@freezed
abstract classLinks with _$Links {
const factory Links({
String? github,
String? twitter,
String? website,
}) = _Links;
factory Links.fromJson(Map<String, dynamic> json) =>
_$LinksFromJson(json);
}
@freezed
abstract classPreferences with _$Preferences {
const factory Preferences({
required String theme,
required String language,
required Notifications notifications,
}) = _Preferences;
factory Preferences.fromJson(Map<String, dynamic> json) =>
_$PreferencesFromJson(json);
}
@freezed
abstract classNotifications with _$Notifications {
const factory Notifications({
required bool email,
required bool sms,
required Push push,
}) = _Notifications;
factory Notifications.fromJson(Map<String, dynamic> json) =>
_$NotificationsFromJson(json);
}
@freezed
abstract classPush with _$Push {
const factory Push({
required bool enabled,
required List<String> channels,
}) = _Push;
factory Push.fromJson(Map<String, dynamic> json) =>
_$PushFromJson(json);
}
@freezed
abstract classDevice with _$Device {
const factory Device({
required String type,
required String brand,
String? model,
required OperatingSystem os,
Network? network,
List? connections,
List? apps,
}) = _Device;
factory Device.fromJson(Map<String, dynamic> json) =>
_$DeviceFromJson(json);
}
@freezed
abstract classOperatingSystem with _$OperatingSystem {
const factory OperatingSystem({
required String name,
required String version,
Kernel? kernel,
String? securityPatch,
}) = _OperatingSystem;
factory OperatingSystem.fromJson(Map<String, dynamic> json) =>
_$OperatingSystemFromJson(json);
}
@freezed
abstract classKernel with _$Kernel {
const factory Kernel({
required String type,
required String build,
}) = _Kernel;
factory Kernel.fromJson(Map<String, dynamic> json) =>
_$KernelFromJson(json);
}
@freezed
abstract classNetwork with _$Network {
const factory Network({
String? ip,
String? mac,
List? connections,
}) = _Network;
factory Network.fromJson(Map<String, dynamic> json) =>
_$NetworkFromJson(json);
}
@freezed
abstract classConnection with _$Connection {
const factory Connection({
required String ssid,
required int strength,
required String encryption,
}) = _Connection;
factory Connection.fromJson(Map<String, dynamic> json) =>
_$ConnectionFromJson(json);
}
@freezed
abstract classApp with _$App {
const factory App({
required String name,
required AppPermissions permissions,
}) = _App;
factory App.fromJson(Map<String, dynamic> json) => _$AppFromJson(json);
}
@freezed
abstract classAppPermissions with _$AppPermissions {
const factory AppPermissions({
bool? camera,
bool? contacts,
bool? location,
bool? notifications,
bool? storage,
}) = _AppPermissions;
factory AppPermissions.fromJson(Map<String, dynamic> json) =>
_$AppPermissionsFromJson(json);
}
@freezed
abstract classActivity with _$Activity {
const factory Activity({
required DateTime lastLogin,
required List sessions,
required History history,
}) = _Activity;
factory Activity.fromJson(Map<String, dynamic> json) =>
_$ActivityFromJson(json);
}
@freezed
abstract classSession with _$Session {
const factory Session({
required String device,
required String location,
required String ip,
required DateTime timestamp,
}) = _Session;
factory Session.fromJson(Map<String, dynamic> json) =>
_$SessionFromJson(json);
}
@freezed
abstract classHistory with _$History {
const factory History({
required int logins,
required Actions actions,
}) = _History;
factory History.fromJson(Map<String, dynamic> json) =>
_$HistoryFromJson(json);
}
@freezed
abstract classActions with _$Actions {
const factory Actions({
required int codePushes,
required int issuesOpened,
required int comments,
required Repositories repositories,
}) = _Actions;
factory Actions.fromJson(Map<String, dynamic> json) =>
_$ActionsFromJson(json);
}
@freezed
abstract classRepositories with _$Repositories {
const factory Repositories({
required int active,
required int archived,
required List details,
}) = _Repositories;
factory Repositories.fromJson(Map<String, dynamic> json) =>
_$RepositoriesFromJson(json);
}
@freezed
abstract classRepoDetail with _$RepoDetail {
const factory RepoDetail({
required String name,
required String language,
required List contributors,
}) = _RepoDetail;
factory RepoDetail.fromJson(Map<String, dynamic> json) =>
_$RepoDetailFromJson(json);
}
@freezed
abstract classContributor with _$Contributor {
const factory Contributor({
required String name,
required String role,
}) = _Contributor;
factory Contributor.fromJson(Map<String, dynamic> json) =>
_$ContributorFromJson(json);
}
@freezed
abstract classMeta with _$Meta {
const factory Meta({
required DateTime createdAt,
required DateTime updatedAt,
required String version,
required List<String> tags,
required Status status,
}) = _Meta;
factory Meta.fromJson(Map<String, dynamic> json) => _$MetaFromJson(json);
}
@freezed
abstract classStatus with _$Status {
const factory Status({
required bool active,
required bool verified,
required List<String> roles,
}) = _Status;
factory Status.fromJson(Map<String, dynamic> json) =>
_$StatusFromJson(json);
}

Modos de Salida

Se puede configurar si todas las clases se generan en un solo archivo (one-page) o si cada modelo se separa en su propio archivo (`separated`), incluyendo las importaciones necesarias.

1. Modo one-page

// Contenido de 'user.dart'
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
abstract class User with _$User {
const factory User({
required int id,
required String name,
required Profile profile,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
@freezed
abstract class Profile with _$Profile {
const factory Profile({
required int age,
required String country,
}) = _Profile;
factory Profile.fromJson(Map<String, dynamic> json) =>
_$ProfileFromJson(json);
}

2. Modo separated-page

// Archivo 1: user.dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'profile.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
const factory User({
required int id,
required String name,
required Profile profile,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) =>
_$UserFromJson(json);
}
// Archivo 2: profile.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'profile.freezed.dart';
part 'profile.g.dart';
@freezed
class Profile with _$Profile {
const factory Profile({
required int age,
required String country,
}) = _Profile;
factory Profile.fromJson(Map<String, dynamic> json) =>
_$ProfileFromJson(json);
}

Manejo de Valores null

Cuando una propiedad tiene el valor null en el JSON, se infiere un tipo genérico anulable (String? por defecto), y se añade un comentario para la revisión manual del tipo exacto.

// Propiedad 'avatar' con valor: null en el JSON
@freezed
class User with _$User {
const factory User({
// ...
String? avatar, // //! INFO: Verificar tipo (ajustar si es int?, bool?, etc.)
}) = _User;
}

Formatos de Entrada JSON

1. JSON Quoted (Válido)

Se procesa directamente.

{
"id": 1,
"name": "Elias"
}

2. JSON Unquoted (Claves sin comillas)

Se aplica un formateo automático para agregar las comillas a las claves, luego se genera el código.

{
id: 1,
name: "Elias", // Clave 'name' sin comillas
}

3. Formato Inválido

Si un valor de tipo *string* no está entre comillas (ej. "name": Elias), el parser fallará.

{
"id": 1,
"name": Elias, // <- ERROR JSON inválido: string sin comillas
}
¿Necesitas ejemplos de integración o tienes una duda puntual puedes contactarme mediante mi sitio web?.