Convertidor JSON a Go Struct Gratis

Analiza JSON y genera automáticamente definiciones de struct Go con nombres de campo en PascalCase y etiquetas json para integrarlas sin problemas en tu código Go.

Entrada y salida

Opciones

Cómo funciona

  1. Pega tu JSON: introduce cualquier objeto JSON o estructura anidada en el campo de entrada.
  2. Obtén la struct Go: la definición equivalente de struct Go con nombres de campo, tipos y etiquetas JSON correctos se genera al instante.
  3. Copia y usa: copia el código de la struct y pégalo en tu proyecto Go para empezar a deserializar datos JSON.

¿Por qué usar el convertidor JSON → struct Go?

Escribir structs Go a mano para respuestas JSON complejas es tedioso y propenso a errores, sobre todo cuando la API devuelve objetos profundamente anidados con decenas de campos. JSON → Go automatiza esto analizando la forma del JSON y generando structs Go correctamente tipadas con etiquetas json:"…" apropiadas, que se corresponden con los nombres de campo JSON. Eso acelera el desarrollo Go al consumir API REST, procesar cargas útiles de webhooks o trabajar con cualquier fuente de datos JSON.

Funcionalidades

  • Generación de structs anidadas: los objetos JSON profundamente anidados se convierten en definiciones de struct Go anidadas.
  • Inferencia de tipos: cadenas, números, booleanos, arrays y valores null se asocian a los tipos Go apropiados.
  • Etiquetas JSON: todos los campos incluyen etiquetas de struct json:"fieldName" que corresponden a las claves JSON originales.
  • Gestión de arrays: los arrays JSON se convierten en slices Go con el tipo de elementos correcto.
  • Tipos puntero: los campos JSON nullable se representan como tipos puntero (por ejemplo, *string).

Preguntas frecuentes

¿Cómo se gestionan los valores null?

Los campos JSON null se convierten en tipos puntero en Go (por ejemplo, *string, *int), lo que permite representar tanto nil como un valor real. Así se gestionan correctamente los campos opcionales o nullable en la respuesta de API.

¿Y si el JSON tiene tipos incoherentes?

Si el mismo campo aparece con tipos distintos entre los objetos JSON (frecuente en API reales), el convertidor puede inferir interface{} (any en el Go moderno). Revisa esos campos y añade aserciones de tipo personalizadas si es necesario.

¿Genera el código de deserialización completo?

La herramienta genera las definiciones de struct. Para deserializar, usa json.Unmarshal(data, &myStruct) o json.NewDecoder(r.Body).Decode(&myStruct) con el paquete estándar encoding/json.

Breve historia de Go y JSON

Go fue anunciado en Google por Rob Pike, Robert Griesemer y Ken Thompson en noviembre de 2009; el paquete encoding/json aterrizó en la biblioteca estándar antes de Go 1.0 (marzo de 2012). El parsing JSON en Go se basa en reflexión: declaras un struct, etiquetas los campos con json:"name", y json.Unmarshal recorre tanto el struct como los bytes. El patrón resultó tan productivo que escribir structs a mano para grandes APIs se volvió tedioso rápidamente. Mat Ryer construyó mholt/json-to-go como una herramienta solo JavaScript en 2014 (aún se mantiene en mholt.github.io/json-to-go) usando parsing JSON basado en regex en el navegador. quicktype (David Siegel, 2017) generalizó la idea a 23 lenguajes incluyendo TypeScript, Rust, Swift, Kotlin, Python, Java. easyjson enfocado en rendimiento (Mail.ru, 2016) salta la reflexión generando código de marshalling en tiempo de compilación, 4-5× más rápido que encoding/json para caminos calientes. Go 1.18 (marzo de 2022) añadió genéricos, que simplificaron algunos helpers de marshalling pero no cambiaron el idioma de etiquetas de struct. Go 1.21 (agosto de 2023) añadió el paquete experimental encoding/json/v2 (propuesta aún en discusión a 2024), apuntando a corregir trampas de larga data como incompatibilidades silenciosas de tipos y reflexión lenta.

Struct vs map[string]interface{}: cuándo tiene sentido cada uno

  • Los structs tipados ganan para formas conocidas. Si controlas la API o tienes un schema estable, los structs te dan verificación de campos en tiempo de compilación, autocompletado del IDE y parsing 2-3× más rápido. json.Unmarshal en un struct solo toca campos que reconoce, ignorando silenciosamente las claves JSON desconocidas (a menos que llames decoder.DisallowUnknownFields).
  • Los maps ganan para JSON arbitrario. map[string]interface{} (o en Go 1.18+ map[string]any) maneja formas salvajemente variables, payloads webhook de muchas fuentes, configuraciones de plugins, documentos MongoDB. Compromiso: cada acceso necesita una aserción de tipo (data["age"].(float64)), y los números se parsean como float64 por defecto, perdiendo precisión para enteros grandes.
  • Híbrido: campos conocidos como struct, desconocidos como map. Usa json.RawMessage para diferir el parsing o añade un campo catch-all Extra map[string]interface{} `json:"-,inline"` (con ayuda de bibliotecas como go-restful). Los SDKs Go de Stripe y Twilio usan este patrón para respuestas API con compatibilidad hacia adelante.
  • Brecha de rendimiento. Los caminos calientes (p. ej. parsear 10.000 eventos webhook por segundo) se benefician de marshallers generados: easyjson, ffjson, go-json, sonic (ByteDance, 2022, usa JIT para generar código máquina en runtime, la biblioteca JSON más rápida en Go). El parsing genérico basado en struct maneja quizás 100-200 MB/s; sonic maneja 1-2 GB/s.
  • Streaming para JSON enorme. Un archivo JSON de 1 GB no cabe en memoria. json.Decoder.Token() lee token por token. json.Decoder.More() recorre elementos de array uno a la vez. Usa streaming para archivos de log, datasets grandes, flujos ND-JSON (un objeto JSON por línea, usado por OpenSearch, BigQuery, API de ChatGPT).

Donde la conversión JSON a Go ahorra tiempo real

  • Integración de API REST. Stripe, GitHub, Slack, Notion todos retornan JSON profundamente anidado. Tomar una respuesta de muestra y pegarla en json-to-go produce 80-90% del struct final. Gasta el tiempo ahorrado en el 10% (unmarshallers personalizados para formatos de tiempo, semánticas omitempty, campos puntero opcionales).
  • Manejadores de webhook. Un payload webhook Stripe típico tiene 80-200 campos con 3-5 niveles de anidación. Escribir a mano el struct Go toma 30-60 minutos; pegar el payload de muestra a través de json-to-go toma 30 segundos.
  • Parsing de configuración. Los archivos de configuración JSON (preferidos sobre TOML por AWS Lambda, Docker Compose compose.json, devcontainer.json) mapean limpiamente a structs Go. encoding/json maneja tanto la lectura como la escritura del archivo con el mismo struct.
  • Puentes gRPC y Protobuf. Los tipos Go protobuf generados incluyen etiquetas json. Al transcodificar entre protobuf y JSON (gRPC-Gateway, Buf, Connect), json-to-go ayuda a esbozar el lado Go desde el formato wire JSON.
  • Columnas JSONB de base de datos. PostgreSQL jsonb, documentos MongoDB, columnas JSON MySQL. El driver database/sql retorna []byte que tú unmarshalas en un struct. Los generadores aceleran el primer pase para tablas schema-on-read.
  • Datos fixture para tests. Una respuesta JSON de producción real se vuelve la fixture de test. json-to-go te da el struct para unmarshalar para aserciones. Combinado con directorios testdata/ (convención Go desde 1.10), mantiene los tests cerca de la realidad.
  • Pipelines CSV-a-JSON-a-struct. Para tareas de ingeniería de datos: leer CSV, marshalar como JSON para inspección, pegar en json-to-go para obtener el struct, luego escribir un pipeline tipado. Mucho más rápido que adivinar tipos de columna desde una hoja de cálculo.

Errores comunes después de generar structs

  • Olvidar el manejo de time.Time. encoding/json asume formato RFC 3339 (2026-05-13T12:34:56Z). La mayoría de APIs entregan esto pero algunas usan timestamps Unix (Stripe), ISO sin zona horaria (APIs Microsoft legacy), o cadenas personalizadas. Para no-RFC-3339, define un tipo personalizado con método UnmarshalJSON.
  • Desbordamiento de entero con float64 por defecto. Un número JSON parseado a interface{} se vuelve float64; números por encima de 2^53 pierden precisión. IDs de cliente Stripe, snowflake Twitter, usuarios Discord (todos de 64 bits) necesitan json.Number o int64 en tu struct. Usa json.Decoder.UseNumber() para parsing seguro a interface{}.
  • Malentender omitempty. omitempty omite el campo en marshal si es el valor cero (cadena vacía, 0, puntero nil, slice/map vacío). No significa «opcional en unmarshal». Un campo int con valor 0 es indistinguible de uno faltante; usa *int si necesitas saber si la API omitió el campo o envió cero.
  • Desajustes de caja en nombres de campo. Los campos Go deben ser exportados (capitalizados) para ser marshalados. El nombre JSON por defecto es el nombre Go textualmente, así UserID se convierte en "UserID" en JSON a menos que esté etiquetado. Los generadores añaden etiquetas json:"userId" para puentear PascalCase de Go con camelCase de JSON. Olvidar la etiqueta significa que tu código «funciona» consigo mismo pero falla contra APIs externas.
  • Sobre-usar tipos puntero. Los generadores a veces usan *string o *int por seguridad. Esto hace que cada acceso necesite una verificación nil. Si la API garantiza que el campo siempre está presente (lee la documentación de la API), usa el tipo valor y salta la indirección.
  • Tipos inconsistentes entre respuestas. Algunas APIs retornan tags: []string{"foo"} en una respuesta y tags: "foo" como cadena en otra. La generación pura de código no puede puentear esto. Escribe un UnmarshalJSON personalizado que maneje ambos casos, o cambia a interface{} y documenta la variabilidad.
  • Eliminación silenciosa de campos desconocidos. Por defecto, json.Unmarshal ignora las claves JSON no en el struct. Esto es a menudo un bug: la API añadió un campo, tu código no lo sabe. Usa decoder.DisallowUnknownFields() en tests para atrapar derivas; en producción mantenlo permisivo.

Más preguntas frecuentes

¿En qué difiere esto del canónico mholt/json-to-go?

Mismo algoritmo central: parsear el JSON, inferir tipos de la primera ocurrencia de cada campo, generar un struct con campos etiquetados entre backticks. Esta implementación corre completamente en tu navegador sin analíticas ni llamadas de red; la canónica está alojada en mholt.github.io/json-to-go, también solo-navegador pero en un dominio diferente. La salida debería coincidir para ~95% de las entradas; casos límite (arrays de tipos mixtos, structs anónimos profundamente anidados) pueden diferir ligeramente. Si necesitas una salida mholt exacta, usa esa; si necesitas garantías de privacidad de que el JSON nunca deje tu dispositivo, usa esta.

¿Por qué algunos campos se generan como interface{}?

Tres razones habituales. Primero, literal null en el JSON fuente: el generador no puede inferir un tipo útil solo de null, así que retrocede a interface{}. Reemplaza con un puntero tipado (*string, *int) una vez que conozcas el schema real. Segundo, arrays de tipos mixtos: [1, "two", true] no puede ser un slice tipado. Tercero, campo completamente ausente en tu muestra, pega un JSON más representativo si está disponible. En Go 1.18+ puedes reemplazar interface{} con el alias más limpio any; son idénticos a nivel de tipo.

¿Puedo hacer ida y vuelta del JSON a través de este struct sin perder datos?

Generalmente sí, con salvedades. encoding/json preserva valores de campo pero no orden de campo (la spec JSON dice que el orden de campo es irrelevante; los maps Go son deliberadamente aleatorios). Precisión numérica: los int64 por encima de 2^53 hacen ida y vuelta seguramente como int64 Go, pero si alguna vez casteas a float64 o envías a través de JavaScript (p. ej. intermediario navegador) pierdes dígitos. Los campos JSON desconocidos se eliminan silenciosamente en unmarshal-luego-remarshal, presérvalos con un catch-all map[string]json.RawMessage si la fidelidad de ida y vuelta importa.

¿Cuándo debería usar código struct generado (easyjson, sonic) en lugar de encoding/json?

Por defecto encoding/json: es suficientemente bueno para 95% de los servicios y viene con el lenguaje. Cambia a easyjson o sonic cuando hayas perfilado y el marshalling JSON aparezca en tu flame graph de CPU a >10% del tiempo total. Puntos de quiebre típicos: servicios HTTP manejando miles de peticiones por segundo, agregadores de log ingiriendo GBs/hora, feeds en tiempo real. Ambas alternativas mantienen las mismas definiciones de struct y etiquetas, así que puedes cambiarlas sin cambiar las declaraciones de campo.

¿Se envía mi JSON a algún servidor?

No. El parsing JSON y la generación de código Go ambos corren en JavaScript en tu dispositivo. Abre la pestaña Network en DevTools mientras pegas; verás cero peticiones salientes. Seguro para respuestas de API propietarias, fixtures de datos de clientes, payloads webhook con PII, y cualquier cosa cubierta por un NDA.