Input (schema .proto)

Output (JSON Schema)

Cosa fa questo strumento

Hai uno schema Protocol Buffers e un servizio che riceve JSON — magari un handler di webhook, magari un gateway gRPC con HTTP transcoding, magari un API gateway che valida la richiesta prima che arrivi al tuo codice. Vuoi un documento JSON Schema che rispecchi il proto per validare payload in ingresso, generare frammenti di OpenAPI o passarlo in prompt di structured output. Questo convertitore lo fa nel tuo browser — incolla il .proto, copia il JSON Schema, mettilo nella config del tuo validatore.

L'output è JSON Schema draft 2020-12 — il draft attuale, supportato da ogni validatore moderno incluso Ajv. Ogni message diventa una entry sotto $defs con type: "object" e una mappa properties. Ogni enum diventa una entry di $defs con type: "string" e i nomi di valore elencati sotto enum — allineato a come proto3 serializza gli enum per nome in JSON. I riferimenti ai field si risolvono via $ref: "#/$defs/MessageName" usando il nome leaf, così i tipi annidati restano leggibili.

Il mapping dei tipi segue la spec di mapping proto3-JSON. string/bool mappano direttamente. Gli int a 32 bit diventano type: "integer" con format: "int32"; gli unsigned 32 bit aggiungono minimum: 0. Gli int a 64 bit diventano type: "string" con format: "int64" e un pattern numerico, perché i Number JSON perdono precisione sopra 2^53 e proto3 codifica gli interi a 64 bit come stringhe quotate sul wire. bytes diventa una stringa con contentEncoding: "base64". I tipi well-known come google.protobuf.Timestamp mappano a format: "date-time" secondo RFC 3339. La conversione gira interamente nel tuo browser — il tuo schema non lascia la pagina.

Come si usa

Tre passi. L'output è un singolo documento JSON Schema che puoi passare dritto a un validatore.

1

Incolla il tuo schema .proto

Lascia cadere lo schema nell'editor a sinistra. syntax = "proto3"; in cima va bene ma è opzionale. Il parser gestisce blocchi message annidati, dichiarazioni enum, oneof, map<K, V> e field options. Le direttive import sono riconosciute ma saltate — incolla i tipi importati inline se ti servono.

I nomi dei field restano in snake_case (allineato a quello che l'encoder JSON proto3 emette di default — nessuna trasformazione). Se il tuo client setta preserve_proto_field_names = false, cambia a mano le chiavi delle proprietà in camelCase.

2

Leggi lo schema

Sulla destra: un documento JSON Schema 2020-12 con $id, title, un $ref top-level che punta all'ultimo message radice dichiarato, e un blocco $defs che contiene ogni message ed enum del file. Ogni message diventa uno schema d'oggetto con una mappa properties; ogni enum diventa uno schema string con i nomi di valore. Leggi la guida Understanding JSON Schema se ti serve un ripasso sulla semantica di $ref o $defs.

3

Collegalo a un validatore

Salva l'output come schema.json, caricalo in Ajv (Node) o jsonschema (Python) o nel validatore che usa il tuo stack, poi lancialo contro il JSON che la tua gRPC-gateway o il webhook ricevono. I mismatch escono come path d'errore leggibili tipo /items/0/sku must be string. Lo stesso schema può anche alimentare definizioni di componenti OpenAPI 3.1 o prompt di structured output per un LLM.

Quando ti fa risparmiare tempo davvero

Validare webhook definiti in proto

Il tuo team usa Protobuf come fonte di verità per un evento OrderShipped, ma il vero ricevitore del webhook prende JSON — non c'è proto runtime sul ricevitore. Incolla il .proto, butta il JSON Schema in Ajv e rifiuta payload malformati al confine prima che arrivino alla logica di business. Una SKU-101 senza quantity non arriva mai al database.

Costruire OpenAPI 3.1 da schemi gRPC

Stai scrivendo spec OpenAPI 3.1 per una gRPC-gateway. OpenAPI 3.1 è compatibile con JSON Schema 2020-12, quindi il blocco $defs qui cade dritto sotto components.schemas dopo un piccolo rinominamento. Niente plugin protoc-gen-openapi da installare, niente Buf CLI da configurare — solo incollare, modificare, committare.

Structured output LLM da un proto

Vuoi che OpenAI o Anthropic restituiscano un oggetto Order tipizzato che combaci con il tuo .proto esistente. Incolla lo schema, prendi la entry $defs/Order e passala come JSON Schema in response_format. Il modello ora produce output che fa round-trip nel tuo servizio gRPC senza coercion manuali.

Reviewing di un cambio di API Protobuf

Un compagno di backend ha aggiunto due field a Address e rinominato un valore di enum. Vuoi vedere come questo impatta il JSON Schema usato dalla tua gateway senza far partire l'intera pipeline di codegen. Incolla il nuovo .proto, fai il diff dello schema contro la copia committata, lascia un commento di review mirato sulla PR.

Domande comuni

Il mio schema viene mandato da qualche parte?

No. Il parser e l'emitter di JSON Schema girano interamente nel tuo browser come JavaScript. Apri i DevTools e guarda il tab Network mentre incolli — zero richieste. Utile quando lo schema include path di package interni, nomi di tipo o qualunque cosa che non vorresti passare a un servizio terzo.

Quale draft di JSON Schema viene preso di mira dall'output?

Draft 2020-12, il draft pubblicato attuale. L'URI $schema su ogni documento di output è https://json-schema.org/draft/2020-12/schema. Vedi le release notes 2020-12 per cosa è cambiato dal 2019-09. Ogni validatore mantenuto attivamente (Ajv 8+, jsonschema 4+ per Python, NJsonSchema, Justify per Java) supporta 2020-12 di default.

Perché i field int64 sono stringhe, non integer?

Perché è quello che dice la spec di mapping proto3-JSON, e ha ragione. I Number JSON sono double IEEE-754, che perdono precisione sopra 2^53. Un vero int64 può portare valori molto oltre quel tetto — ID di ordine, timestamp in nano, saldi di ledger — quindi proto3 codifica gli interi a 64 bit come stringhe JSON quotate. Lo schema lo riflette con type: "string", format: "int64" e un pattern numerico così che un validatore continua a rifiutare "abc". Se il tuo server tira fuori int a 64 bit come Number JSON crudi (alcune gateway legacy lo fanno), cambia a mano quelle entry in { "type": "integer" }.

Perché gli enum sono stringhe, non integer?

Stesso motivo — è il default di encoding JSON di proto3. Gli enum si serializzano come il nome del loro valore ("ORDER_STATUS_PAID") invece che come il numero wire intero (2). Questo rende i payload JSON leggibili e lo schema più semplice. I numeri interi non sono nel JSON Schema perché sono una questione di wire format, non di validazione. Se hai un encoder non-default configurato per emettere int, scambia type: "string" con type: "integer" sulla entry dell'enum.

Come gestisce map<K, V>?

Lo renderizza come { "type": "object", "additionalProperties": <V-schema> }. Le chiavi degli oggetti JSON sono sempre stringhe, quindi una map proto con una chiave non-string (es. map<int32, string>) si becca una nota di description che spiega che le chiavi a runtime saranno coerze a stringa. Lo schema del valore segue le stesse regole di mapping del tipo di un field normale.

I field sono marcati come required?

No — i field di proto3 hanno sempre un default nel wire format e sono sempre presenti nell'output JSON (con default vuoti come "", 0, false, [], {}), quindi lo schema non elenca nulla sotto required. Se vuoi davvero che un field sia required al tempo di validazione, aggiungilo a un array required sul message padre a mano. I field optional di proto3 e oneof non vengono nemmeno forzati come oneOf nell'output — quelle sono semantiche di runtime che JSON Schema non può esprimere pienamente senza annotazioni extra.

Come vengono referenziati i message annidati?

Ogni message ed enum viene tirato su in un blocco $defs piatto indicizzato per nome leaf. I riferimenti ai field passano per $ref: "#/$defs/MessageName". Appiattire tiene il documento compatto e fa sì che i tipi annidati due volte non vengano duplicati. Se due message in package diversi condividono un nome leaf, il convertitore tiene la prima definizione — separa i nomi in conflitto prima di incollare se la cosa conta.

Posso piazzare questo dritto in Ajv?

Sì. ajv.compile(schema) sull'output funziona out of the box una volta che Ajv è configurato per draft 2020-12 (new Ajv2020() da ajv/dist/2020). Le entry $ref si risolvono internamente perché tutto è nello stesso documento. Se vuoi la validazione di format (date-time, duration), aggiungi ajv-formats insieme.

Strumenti correlati

Se stai armeggiando con Protobuf, JSON Schema e validazione, questi vanno bene insieme: