Convertidor Protobuf a C#
Pega un esquema .proto. Obtén clases C# con auto-properties — listas para soltar directamente en un proyecto, sin necesidad de plugin de protoc.
Entrada (esquema .proto)
Salida (C#)
Qué hace esta herramienta
Tienes un esquema de Protocol Buffers y un servicio o cliente de C# que necesita los DTOs correspondientes. La vía oficial es instalar protoc con el plugin de C# (o conectar Grpc.Tools a tu .csproj) y dejar que MSBuild genere las clases parciales durante la compilación. Eso funciona, pero es excesivo cuando solo quieres leer el esquema, esbozar tipos o pegar un mensaje en una página Razor o una integración puntual. Este conversor hace el mismo tipo de trabajo — pega, copia, suéltalo en Types.cs.
El mapeo de tipos es de los aburridos pero correctos. string sigue siendo string (con inicializador = "" para que los proyectos con nullable references no se quejen). bool, int32, int64, uint32, uint64, float, double se mapean a bool, int, long, uint, ulong, float, double respectivamente. bytes pasa a byte[]. repeated T se convierte en List<T>, map<K, V> en Dictionary<K, V>, y los wrappers conocidos como google.protobuf.Timestamp se emiten como string (la codificación JSON de proto3 para timestamps es RFC 3339, que a nivel de wire es solo una cadena — mira la spec JSON de proto3 si necesitas los detalles).
Los nombres de campo reciben el tratamiento PascalCase estándar — order_id → OrderId, shipping_address → ShippingAddress — igual que la referencia oficial de protobuf para C#. Los valores de enum pierden el prefijo SCREAMING_SNAKE cuando el esquema sigue la convención de prefijar cada valor con el nombre del enum (así que ORDER_STATUS_PENDING en enum OrderStatus pasa a ser OrderStatus.Pending). Las clases de salida son planas — cada mensaje anidado se sube al nivel superior para que puedas separarlas o reordenarlas sin desenredar ámbitos. La conversión ocurre íntegramente en tu navegador; nada del esquema se sube a ningún sitio.
Cómo usarla
Tres pasos. La salida está lista para compilar — pégala en un archivo <code>Types.cs</code> de tu proyecto.
Pega tu esquema .proto
Suelta el esquema en el editor de la izquierda. syntax = "proto3"; al principio es opcional. El parser maneja bloques message anidados, declaraciones enum, oneof, map<K, V>, opciones de campo y las directivas habituales package/import/option. Los imports se reconocen pero se omiten, así que pega cualquier tipo importado en línea si tu esquema depende de él.
La conversión de nombres de campo es automática: customer_name en .proto pasa a CustomerName en C#. Los nombres de clases y enums se mantienen tal cual (ya van en PascalCase por convención).
Lee la salida
A la derecha: declaraciones public class con auto-properties { get; set; } para cada mensaje, más declaraciones public enum para cada enum. Se añade una línea using System.Collections.Generic; cuando el esquema usa campos repeated o map (para que List y Dictionary resuelvan). Suelta el archivo en un proyecto, envuélvelo en tu namespace y listo.
Conéctalo
Para uso puro de DTO, las clases están listas para serializar con System.Text.Json o Newtonsoft.Json. Para trabajo real con gRPC en C# — implementaciones de servicio, streaming, deadlines — sigue usando Grpc.Tools para los tipos de wire format, y emplea este conversor para wrappers escritos a mano, capas de mapeo o fixtures de pruebas junto al código generado.
Cuándo ahorra tiempo de verdad
Esbozar DTOs para un nuevo servicio gRPC
Estás arrancando un servicio gRPC en ASP.NET Core y quieres ver qué pinta van a tener los mensajes en C# antes de comprometerte con Grpc.Tools. Pega el .proto, echa un vistazo a las clases, decide si el naming de campos cuadra con el estilo de tu equipo y luego monta la generación de código en condiciones.
Capa de mapeo escrita a mano
Tus tipos generados de gRPC viven en su propio namespace y quieres DTOs sin adornos para tu capa de dominio. La salida de aquí te da clases limpias sin el ruido de metadatos del código generado — fácil de mapear con AutoMapper o convertidores hechos a mano.
Revisar un cambio en un esquema Protobuf
Un compañero añadió campos a un mensaje en un PR. Quieres ver el impacto en la forma C# sin hacer checkout de la rama y compilar. Pega el nuevo esquema, hazle diff con los tipos C# actuales y deja un comentario de revisión concreto.
Fixtures de tests y scripts rápidos
Estás escribiendo un script LinqPad puntual o una app de consola que hace POST a un gRPC-gateway. Montar todo el toolchain de Protobuf para 50 líneas de código de prueba es excesivo. Saca las clases de aquí, serialízalas a JSON, manda la petición y sigue adelante.
Preguntas frecuentes
¿Se envía mi esquema a algún sitio?
No. El parser y el emisor de C# corren íntegramente en tu navegador como JavaScript. Abre las DevTools y mira la pestaña Network mientras pegas — cero peticiones. Útil cuando tu esquema incluye nombres de tipos internos, rutas de paquetes o cualquier cosa que no quieras enviar a un servicio de terceros.
¿Estas clases funcionan con el código generado por Grpc.Tools?
Producen formas equivalentes, pero no son idénticas byte a byte. Grpc.Tools genera clases parciales, registros de parser, cableado de descriptors y tipos ancestros desde Google.Protobuf.IMessage — nada de eso está aquí. Para trabajo real con el protocolo de wire de gRPC, usa Grpc.Tools. Para código exclusivo de DTOs (por ejemplo, gateways JSON-sobre-HTTP, capas de mapeo, datos de test), esta salida vale.
¿Por qué int64 y uint64 se tipan como long y ulong en lugar de string?
Porque en C# caben. A diferencia de los Number de JavaScript (que pierden precisión por encima de 2^53), long de C# maneja todo el rango de int64 de forma nativa, así que no hay razón para caer en string. Si estás deserializando JSON proto3 donde los enteros de 64 bits llegan como cadenas (según la spec de mapeo JSON), System.Text.Json con JsonNumberHandling.AllowReadingFromString hace la conversión.
¿Cómo gestiona la convención de valores de enum en SCREAMING_SNAKE?
La guía de estilo de Protobuf recomienda prefijar cada valor de enum con el nombre del enum en SCREAMING_SNAKE. El conversor lo detecta y lo elimina. ORDER_STATUS_UNSPECIFIED en el enum OrderStatus pasa a OrderStatus.Unspecified. Si tu enum no sigue esa convención (algunos valores con prefijo, otros no), se omite el strip y los valores se ponen en PascalCase tal cual.
¿Maneja oneof?
Cada campo de un oneof se emite como una auto-property normal. La salida no impone la restricción de "exactamente uno" que implica oneof — el lenguaje C# todavía no tiene discriminated unions nativos. Si necesitas un modelado más estricto, mira librerías como OneOf en NuGet, o edita la salida a mano para usar una clase base con subclases.
¿Y google.protobuf.Timestamp y los well-known types?
Timestamp se emite como string (proto3 JSON codifica los timestamps como cadenas RFC 3339). Empty y Any se convierten en placeholders object — ajústalos a Google.Protobuf.WellKnownTypes.Any o a un tipo más fuerte si tu proyecto incluye el paquete WKT. La salida es deliberadamente sin framework para que puedas soltarla en cualquier proyecto C# sin forzar una dependencia NuGet.
Herramientas relacionadas
Si andas haciendo malabares entre Protobuf, JSON y C#, estas combinan bien: