Cómo generar clases C# a partir de una muestra JSON

Pega una muestra JSON —una respuesta de API, un archivo de configuración o el cuerpo de un webhook— y esta página escribe las clases C# que le corresponden: una clase por forma de objeto, con propiedades públicas y accesores { get; set; }, todo en un único archivo que puedes copiar. La conversión se ejecuta en tu navegador, la carga nunca se sube y la página sigue funcionando sin conexión una vez cargada.

Cada nombre de propiedad es un identificador legal de C#: una clave que choca con una palabra reservada se escribe como identificador literal (@class) y una clave con caracteres que C# no admite se reconstruye conservando la clave original en un atributo [JsonPropertyName], de modo que System.Text.Json sigue mapeando la carga. Los tipos, los nombres de clase y el anidamiento se deducen de la muestra que pegaste, por eso el resultado es un borrador que conviene revisar y no un modelo terminado.

  1. Pega o escribe el JSON en el campo de arriba. Se admiten comentarios: una línea // o /* */ que esté sola encima de una propiedad se convierte en una línea /// <summary> en la clase generada.
  2. Pulsa Generar clases C#. El archivo aparece debajo, coloreado con la gramática de C#, y el mensaje superior confirma la ejecución o indica la línea que la detuvo.
  3. Pulsa Copiar clases C# para poner el código sin colores en el portapapeles y pégalo en un archivo .cs de tu proyecto.
  4. Edita el JSON y vuelve a generar cuando un valor no cuadre: el resultado anterior se borra en cada ejecución, también cuando falla, así que lo que copias siempre pertenece a la entrada actual.

Cómo se convierten valores, claves y arrays en C#

Qué tipo de C# recibe cada valor JSON

Los números se tipan por rango: un entero que cabe en Int32 se convierte en int, un entero mayor se convierte en long hasta 2^53, y lo que tenga decimales o supere ese límite se convierte en double, así que 2147483648 o 1e10 ya no acaban en un int. true y false se convierten en bool, y un valor que es null en toda la muestra se convierte en string. Una cadena sigue siendo string salvo que tenga forma de fecha y se pueda interpretar como tal: 2024-05-06, 2024/05/06 10:00, 12/31/2024 y May 6, 2024 se convierten en DateTime, mientras que 20240506, 1-2, R2D2 y los identificadores numéricos conservan su texto exacto.

Cuando un mismo campo lleva tipos distintos en los elementos de un array, gana el tipo numérico más amplio (int con long da long, int con 2.5 da double) y cualquier otro desacuerdo se convierte en object. Un campo que es null en un elemento y tiene tipo en otro toma el tipo del elemento no nulo, de modo que un null no borra lo que muestran las demás filas.

Cómo se convierte una clave JSON en una propiedad C#

La propiedad conserva la clave JSON siempre que C# lo permita. Una clave que es palabra reservada se escribe como identificador literal, así que class se convierte en @class, que compila y sigue mapeando la clave del mismo nombre. Una clave con caracteres que C# rechaza se reconstruye: user-name pasa a userName, first name a firstName, 1st a _1st, a.b a aB y una clave vacía a value. Dos claves que acaban en el mismo identificador reciben un sufijo numérico en lugar de sobrescribirse, así que a.b y a&b quedan como aB y aB2.

Cuando el nombre de la propiedad difiere de la clave JSON, la propiedad lleva [JsonPropertyName("...")] y el archivo añade un using System.Text.Json.Serialization; el atributo se omite si solo repetiría el nombre de la propiedad, y una clave que es palabra reservada como class no lo necesita porque el nombre literal ya coincide. Ese atributo es la única configuración que se escribe en el archivo: sin opciones de serializador, sin esquema y sin anotaciones para las claves que no cambiaron.

Objetos, arrays y clases anidadas

Cada forma de objeto distinta se convierte en una clase, nombrada a partir de su clave JSON en PascalCase y nunca repetida dentro del archivo: un segundo data pasa a Data2 y un data anidado dentro de wrap pasa a WrapData, de modo que dos ramas ya no pueden reclamar las dos Data. Una clase tampoco se llama nunca como los tipos que el propio archivo usa (List, String, Object, DateTime), porque ese nombre los ocultaría, y un miembro nunca puede repetir el nombre de su propia clase.

Los arrays se leen completos, no solo por su primer elemento: [1, 2, 3] se convierte en List<int>, [1, 2.5] en List<double>, un array de objetos en una lista de una clase fusionada que contiene todas las claves que aparecen en cualquier elemento, y un array que mezcla objetos con escalares en List<object>. Un array vacío se convierte en List<string> como marcador. El objeto raíz se llama siempre Root; un array en la raíz se anota en un comentario y se modela a partir de sus elementos fusionados, y una raíz escalar produce una clase vacía con un comentario que indica que no se pudieron deducir propiedades.

Qué es el archivo generado y qué no es

La salida es un único archivo de código C#: un comentario de generación con la marca de tiempo, las directivas using que el archivo realmente necesita y después las clases. Es C# plano, con propiedades { get; set; }, sin constructor y sin namespace, así que encaja en cualquier proyecto desde .NET Core 3.0; aquí nada lo compila, la página solo escribe el texto.

Los tipos provienen de la única muestra que pegas, así que un campo que siempre vale 0 en la muestra se tipa int aunque producción envíe un decimal, y un array que está vacío por casualidad se tipa List<string>. Trata el resultado como un borrador: revisa los tipos en los que confías, renombra la clase raíz a tu gusto y conserva los comentarios JSON de la muestra, porque son la única parte de la entrada que se convierte en documentación.

Herramientas recientes: