Skip to content
| Marketplace
Sign in
Visual Studio>Tools>ArjuyJson Tools
ArjuyJson Tools

ArjuyJson Tools

ArjuyJson

|
34 installs
| (1) | Free
Tool Window para trabajar con JSON sin salir de Visual Studio. - Formatear: pretty-print con indentación legible. - Minificar: compacta el JSON para configs/env vars. - Validar: resalta en ROJO, sobre el propio editor, la línea exacta del error. - JSON a C#: genera clases POC...
Download

ArjuyJson Tools

Extensión de Visual Studio (VSIX) que agrega una Tool Window para trabajar con JSON sin salir del IDE: formatear, validar, minificar, convertir JSON ↔ C#, y más — todo con theming nativo del Shell de Visual Studio (Claro, Oscuro, Azul, Alto Contraste).

Vista previa de ArjuyJson Tools

Requisitos

  • Visual Studio 2022 (17.x) o superior.
  • Workload "Visual Studio extension development" instalado (VS Installer → Modificar → marcar el workload).

Instalación

  1. Cloná el repo:
    git clone https://github.com/ajflores/arjuyJson.git
    
  2. Abrí arjuyJsonApp\ArjuyJsonApp.sln en Visual Studio.
  3. Compilá (Build > Build Solution). El .vsix queda en ArjuyJsonApp\bin\Debug\net472\ArjuyJsonApp.vsix (o bin\Release si compilaste en Release).
  4. Doble click al .vsix para instalarlo en tu Visual Studio, o F5 desde el proyecto para probarlo en una instancia experimental sin instalarlo de forma permanente.
  5. Una vez instalada, abrila desde Tools → ArjuyJson Tools (o buscá "ArjuyJson" con Ctrl+Q, el Quick Launch de VS).

Funcionalidades

Formatear

Pretty-print de un JSON: agrega indentación legible.

Input:

{"producto":"Teclado Mecánico","precio":45.99,"stock":25,"activo":true}

Output:

{
  "producto": "Teclado Mecánico",
  "precio": 45.99,
  "stock": 25,
  "activo": true
}

Validar

Detecta si Entrada es válida como JSON o como C# (prueba JSON primero; si falla, prueba como clases C# antes de reportar error) y, en cualquiera de los dos casos, resalta en rojo directamente sobre el editor de entrada la línea exacta del error (no solo un mensaje de texto) — el editor de input usa AvalonEdit justo para poder hacer esto.

Input (con un error real: falta una coma):

{
  "producto": "Teclado Mecánico",
  "precio": 45.99
  "stock": 25,
  "activo": true,
  "categoria": {
    "nombre": "Periféricos",
  }
}

Resultado: el editor resalta la línea 4 ("stock": 25,) en rojo, y el mensaje de estado indica: Línea 4, posición 2: '"' is invalid after a value.... Además, la coma final después de "Periféricos" (línea 7) también se detecta como error — inválida en JSON estricto, sin importar qué motor de serialización tengas seleccionado (ver más abajo).

Si pegás C# en vez de JSON, Validar lo reconoce igual: prueba interpretarlo como clases POCO y, si falta una llave de cierre en una propiedad, resalta esa línea puntual (no una línea genérica) con un mensaje corto tipo Revisá la línea 21: la propiedad no cierra su "{ get; set; }" en la misma línea.. Si Entrada no es válida ni como JSON ni como C#, se muestran los dos mensajes de error (uno por cada intento), para no esconder información sobre cuál de los dos formatos "quisiste" pegar.

Buscar / Limpiar (editor de Entrada)

Junto al editor de Entrada hay dos botones:

  • Buscar: abre el panel de búsqueda nativo de AvalonEdit (resalta todas las coincidencias y hace scroll automático a la actual). No usa el atajo Ctrl+F porque, dentro de una Tool Window de Visual Studio, ese atajo lo intercepta el propio "Buscar" global del IDE antes de que le llegue al editor — por eso es un botón explícito.
  • Limpiar: vacía el contenido de Entrada con un clic.

Minificar

Lo inverso de Formatear: compacta el JSON quitando espacios y saltos de línea. Útil para pegar en archivos de configuración o variables de entorno.

Input:

{
  "a": 1,
  "b": [1, 2]
}

Output:

{"a":1,"b":[1,2]}

JSON a C#

Genera clases C# (POCO, con { get; set; }) a partir de un JSON de ejemplo. Infiere tipos automáticamente (string, int, long, double, bool, objetos anidados, List<T>), y detecta el tipo numérico correcto según el valor (45.99 → double, 25 → int). El namespace y el nombre de la clase raíz son configurables desde dos campos junto al botón (default arjuy.model / Root si se dejan vacíos) — todas las clases generadas, incluidas las anidadas, quedan envueltas en el namespace elegido.

Input:

{
  "nombre_cliente": "Ana",
  "edad": 34,
  "saldo": 1250.75,
  "activo": true,
  "direccion": { "calle": "Av. Siempre Viva", "numero": 742 },
  "compras": [
    { "producto": "Notebook", "precio": 899.99 }
  ]
}

Output (con el checkbox "Agregar [JsonPropertyName]" tildado — agrega el atributo a TODAS las propiedades, para que el mapeo funcione sin importar cómo esté casing-eado el JSON original):

public class Root
{
    [JsonPropertyName("nombre_cliente")]
    public string NombreCliente { get; set; }

    [JsonPropertyName("edad")]
    public int Edad { get; set; }

    [JsonPropertyName("saldo")]
    public double Saldo { get; set; }

    [JsonPropertyName("activo")]
    public bool Activo { get; set; }

    [JsonPropertyName("direccion")]
    public Direccion Direccion { get; set; }

    [JsonPropertyName("compras")]
    public List<Compra> Compras { get; set; }
}

public class Direccion
{
    [JsonPropertyName("calle")]
    public string Calle { get; set; }

    [JsonPropertyName("numero")]
    public int Numero { get; set; }
}

public class Compra
{
    [JsonPropertyName("producto")]
    public string Producto { get; set; }

    [JsonPropertyName("precio")]
    public double Precio { get; set; }
}

(el ejemplo omite el namespace { ... } que envuelve todo por brevedad — con los defaults, sería namespace arjuy.model { ... })

Si el JSON tiene un array vacío ("adjuntos": []) sin ítems de los que inferir el tipo, la propiedad generada es public List<object> Adjuntos { get; set; } // TODO: tipo no inferible, array vacío — el comentario va siempre DESPUÉS de { get; set; }, nunca adentro del tipo, así el código compila igual y se puede pegar tal cual de vuelta en "C# a JSON" sin romper el parseo.

C# a JSON

El camino inverso: pegás clases C# (el mismo patrón simple public class X { public Tipo Prop { get; set; } }, con soporte de List<T> y clases anidadas) y genera un JSON de ejemplo. Como una clase C# solo define tipos, no valores reales, el JSON se completa con datos de ejemplo generados por heurística según el nombre y tipo de cada propiedad — nunca datos inventados con forma "falsa" tipo null/0 para todo.

Input:

public class PedidoDto
{
    public int IdPedido { get; set; }
    public string Cliente { get; set; }
    public decimal Total { get; set; }
    public bool Pagado { get; set; }
    public List<ItemPedido> Items { get; set; }
}

public class ItemPedido
{
    public string Sku { get; set; }
    public int Cantidad { get; set; }
    public double PrecioUnitario { get; set; }
}

Output (valores de ejemplo — cambian en cada ejecución):

{
  "IdPedido": 7,
  "Cliente": "texto_ejemplo_1",
  "Total": 9416.32,
  "Pagado": true,
  "Items": [
    { "Sku": "texto_ejemplo_2", "Cantidad": 90, "PrecioUnitario": 6482.47 },
    { "Sku": "texto_ejemplo_3", "Cantidad": 5, "PrecioUnitario": 6282.27 }
  ]
}

Notá que Total (tipo decimal) recibió un valor con forma de moneda — la heurística reconoce nombres como Precio/Monto/Saldo/Total/Costo y genera valores en un rango realista, en vez de un número al azar sin sentido. Otras heurísticas de nombre: Email/Correo → email de ejemplo, Telefono/Phone → formato 11-XXXX-XXXX, Nombre/Name → nombre real de una lista, Calle/Direccion/Address → dirección, Ciudad/City → ciudad, Edad/Age → rango 18-80, y cualquier propiedad terminada en Id → un entero tipo identificador.

Tipos soportados: string, int, long, double, decimal, bool, DateTime/DateTime?, Guid/Guid?, object (valor null de ejemplo), enums propios definidos en el mismo texto (usa el primer miembro como valor de ejemplo), List<T>/IEnumerable<T>/ICollection<T>/IList<T> (las 4 se generan como el mismo JSON array), arrays (T[], incluido byte[]), Dictionary<TKey,TValue> (clave de ejemplo genérica, valor real del tipo TValue, incluso si TValue es otra clase), clases anidadas definidas en el mismo texto, propiedades con init (records C# 9+) además de set, y record/record class como declaración de tipo raíz — no solo class. Atributos de una sola línea ([Key], [Column("...")], con o sin comentario // inline) se toleran y se descartan sin romper el parseo.

Límites, a propósito y documentados (no es Roslyn, es un parser de texto liviano — decisión consciente para no sumar ~10-20MB al VSIX): NO soporta herencia, structs, atributos multilínea, ni generics distintos de los listados arriba. Toda propiedad debe cerrar { get; set; }/{ get; init; } en una sola línea física. Si el texto no matchea el patrón esperado, la herramienta lo dice explícitamente en vez de devolver un JSON inventado — y si falta una llave de cierre, señala la línea física exacta (de la propiedad, no de la clase) en vez de un mensaje genérico.

Limpiar Escapes

Resuelve un problema muy específico y muy común: cuando copiás el valor de una variable string desde el debugger de Visual Studio (Locals/Watch/Quick Watch), VS te lo muestra con los caracteres escapados tal cual — \r\n en vez de saltos de línea reales, \" en vez de comillas. Este botón lo desescapa para que puedas Formatear/Validar el JSON real que hay debajo.

Input (copiado tal cual del Watch window de VS):

{\r\n  \"Nombre\": \"Ana Martinez\",\r\n  \"Edad\": 58,\r\n  \"Direccion\": {\r\n    \"Calle\": \"Av. Corrientes 1234\",\r\n    \"Ciudad\": \"Rosario\"\r\n  }\r\n}

Output:

{
  "Nombre": "Ana Martinez",
  "Edad": 58,
  "Direccion": {
    "Calle": "Av. Corrientes 1234",
    "Ciudad": "Rosario"
  }
}

Funciona tanto si copiaste el valor CON las comillas envolventes que muestra VS, como si copiaste solo el contenido interno — la herramienta detecta ambos casos automáticamente.

Selector de motor: System.Text.Json / Newtonsoft.Json

Formatear, Validar y Minificar pueden correr sobre System.Text.Json (motor por defecto, nativo de .NET) o Newtonsoft.Json — útil si tu proyecto ya depende de Newtonsoft y querés confirmar que el comportamiento de parseo es el mismo que vas a tener en producción. Ambos motores dan resultados consistentes ante el mismo input (por ejemplo, los dos detectan comas finales inválidas de la misma forma).

Normalización de Casing

Convierte las keys de un JSON (no los valores) a camelCase o PascalCase, recursivamente en objetos anidados.

Input (keys mezcladas, a propósito feas):

{"Nombre_Cliente":"Ana","direccion_envio":{"Calle_Principal":"9 de Julio","numero-piso":3}}

Output con camelCase:

{"nombreCliente":"Ana","direccionEnvio":{"callePrincipal":"9 de Julio","numeroPiso":3}}

Copiar al portapapeles

Un botón junto al panel de salida copia el resultado actual con un clic (Clipboard.SetText), sin tener que seleccionar y copiar manualmente.

Arquitectura (para quien quiera contribuir)

  • MVVM estricto: Views/ (XAML + code-behind mínimo) → ViewModels/ (comandos + estado observable) → Services/ (lógica pura, sin dependencia de WPF).
  • Servicios separados por responsabilidad: IJsonSerializationService (Formatear/Validar/Minificar/Casing, con soporte de dos motores) e ICSharpConversionService (JSON↔C#, Limpiar Escapes).
  • Contrato de resultado unificado: todas las operaciones devuelven un objeto que implementa IOperationResult (Success + ErrorMessage), nunca dejan propagar una excepción cruda hasta la UI.
  • Input implementado con AvalonEdit (no un TextBox plano) para poder resaltar la línea exacta de un error de validación — tanto de JSON (vía JsonException) como de C# (CSharpClassTextParser trackea número de línea real durante el parseo), y para el buscador nativo (SearchPanel, con MarkerBrush y el color de hipervínculos de email atados a VsBrushes en vez de los colores fijos por defecto de la librería).
  • Theming 100% vía VsBrushes/VsColors del Shell de VS — sin colores hardcodeados, respeta el tema activo del IDE automáticamente.

Stack técnico

  • .NET Framework 4.7.2 (requisito del modelo clásico de extensibilidad VSIX, que corre in-process con devenv.exe)
  • WPF + MVVM
  • System.Text.Json / Newtonsoft.Json
  • AvalonEdit
  • Microsoft.VisualStudio.SDK 17.8.x

Licencia

Sin especificar todavía.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft