Invoer (.proto-schema)

Uitvoer (JSON Schema)

Wat deze tool doet

Je hebt een Protocol Buffers-schema en een service die JSON binnenkrijgt — misschien een webhook handler, misschien een HTTP-transcoded gRPC-gateway, misschien een API-gateway die requests valideert voordat ze je code raken. Je wilt een JSON Schema-document dat het proto spiegelt om binnenkomende payloads te valideren, OpenAPI-fragmenten te genereren of het in structured-output prompts te stoppen. Deze converter doet dat in je browser — plak het .proto, kopieer het JSON Schema, gooi het in je validator-config.

De uitvoer is JSON Schema draft 2020-12 — de huidige draft, ondersteund door elke moderne validator inclusief Ajv. Elke message wordt een entry onder $defs met type: "object" en een properties-map. Elke enum wordt een $defs-entry met type: "string" en de waardenamen onder enum — passend bij hoe proto3 enums op naam serialiseert in JSON. Field-referenties resolven via $ref: "#/$defs/MessageName" met de leaf-naam, dus geneste types blijven leesbaar.

De type-mapping volgt de proto3-JSON-mappingspec. string/bool mappen direct. 32-bit ints krijgen type: "integer" met format: "int32"; unsigned 32-bit voegen minimum: 0 toe. 64-bit ints worden type: "string" met format: "int64" en een numeriek pattern, omdat JSON Numbers boven 2^53 precisie verliezen en proto3 64-bit integers op de wire encodeert als gequote strings. bytes wordt een string met contentEncoding: "base64". Well-known types zoals google.protobuf.Timestamp mappen naar format: "date-time" volgens RFC 3339. De conversie loopt volledig in je browser — je schema verlaat de pagina niet.

Hoe je het gebruikt

Drie stappen. De uitvoer is één enkel JSON Schema-document dat je rechtstreeks aan een validator kunt geven.

1

Plak je .proto-schema

Drop het schema in de linker editor. syntax = "proto3"; bovenaan is prima maar optioneel. De parser handelt geneste message-blokken, enum-declaraties, oneof, map<K, V> en field options af. import-directives worden herkend maar overgeslagen — plak geïmporteerde types inline als je ze nodig hebt.

Field-namen blijven in snake_case (passend bij wat de proto3-JSON-encoder standaard uitstuurt — geen transformatie). Als je client preserve_proto_field_names = false zet, wissel de property-keys handmatig naar camelCase.

2

Lees het schema

Aan de rechterkant: een JSON Schema 2020-12-document met $id, title, een top-level $ref die naar je laatst gedeclareerde root-message wijst, en een $defs-blok met elke message en enum uit het bestand. Elke message wordt een object-schema met een properties-map; elke enum wordt een string-schema met de waardenamen. Lees de gids Understanding JSON Schema als je een opfrisser nodig hebt over $ref- of $defs-semantiek.

3

Hang het aan een validator

Sla de uitvoer op als schema.json, laad het in Ajv (Node) of jsonschema (Python) of welke validator je stack ook gebruikt, en draai het dan tegen de JSON die je gRPC-gateway of webhook binnenkrijgt. Mismatches komen eruit als leesbare error-paden, type /items/0/sku must be string. Hetzelfde schema kan ook OpenAPI 3.1-componentdefinities of structured-output prompts voor een LLM voeden.

Wanneer dit echt tijd scheelt

Webhooks valideren die in proto zijn gedefinieerd

Je team gebruikt Protobuf als source of truth voor een OrderShipped-event, maar de eigenlijke webhook-ontvanger krijgt JSON — er draait geen proto-runtime aan de ontvangerkant. Plak het .proto, drop het JSON Schema in Ajv en wijs malformed payloads aan de edge af voor ze de business logic raken. Een SKU-101 zonder quantity komt nooit in de database.

OpenAPI 3.1 bouwen vanuit gRPC-schemas

Je schrijft OpenAPI 3.1-specs voor een gRPC-gateway. OpenAPI 3.1 is JSON Schema 2020-12-compatibel, dus het $defs-blok hier valt na een kleine renaming-pass direct onder components.schemas. Geen protoc-gen-openapi-plugin om te installeren, geen Buf CLI op te zetten — gewoon plakken, bewerken, committen.

LLM structured outputs vanuit een proto

Je wilt dat OpenAI of Anthropic een getypeerd Order-object teruggeeft dat overeenkomt met je bestaande .proto. Plak het schema, pak de $defs/Order-entry en geef die door als het JSON Schema in response_format. Het model produceert nu output die zonder handmatige coercion een round-trip door je gRPC-service maakt.

Een Protobuf-API-wijziging reviewen

Een backend-collega heeft twee fields aan Address toegevoegd en een enum-waarde hernoemd. Je wilt zien hoe dat het JSON Schema raakt dat je gateway gebruikt zonder de hele codegen-pipeline te draaien. Plak het nieuwe .proto, diff het schema tegen je gecommitte kopie, laat een gerichte review-comment achter op de PR.

Veelgestelde vragen

Wordt mijn schema ergens naartoe gestuurd?

Nee. De parser en de JSON Schema-emitter draaien volledig in je browser als JavaScript. Open de DevTools en kijk naar de Network-tab terwijl je plakt — nul requests. Handig wanneer je schema interne package-paden, type-namen of iets anders bevat dat je niet aan een derde partij wilt geven.

Op welke JSON Schema-draft mikt de uitvoer?

Draft 2020-12, de huidige gepubliceerde draft. De $schema-URI op elk uitvoerdocument is https://json-schema.org/draft/2020-12/schema. Zie de 2020-12 release notes voor wat er sinds 2019-09 veranderd is. Elke actief onderhouden validator (Ajv 8+, jsonschema 4+ voor Python, NJsonSchema, Justify voor Java) ondersteunt 2020-12 standaard.

Waarom zijn int64-fields strings, geen integers?

Omdat de proto3-JSON-mappingspec dat zegt, en dat klopt ook. JSON Numbers zijn IEEE-754 doubles, die boven 2^53 precisie verliezen. Een echte int64 kan waarden dragen die ver boven dat plafond uitgaan — order-ID's, timestamps in nanos, ledger-saldi — dus proto3 encodeert 64-bit integers als gequote JSON-strings. Het schema reflecteert dat met type: "string", format: "int64" en een numeriek pattern zodat een validator nog steeds "abc" afwijst. Als je server 64-bit ints als rauwe JSON Numbers uitlevert (sommige legacy-gateways doen dat), verander die entries handmatig naar { "type": "integer" }.

Waarom zijn enums strings, geen integers?

Zelfde reden — dat is de default JSON-encoding van proto3. Enums serialiseren als hun waardenaam ("ORDER_STATUS_PAID") in plaats van het integer wire-nummer (2). Dat maakt JSON-payloads leesbaar en het schema simpeler. De integer-nummers staan niet in het JSON Schema omdat ze een wire-format-zaak zijn, geen validatiezaak. Als je een non-default encoder hebt geconfigureerd om ints uit te sturen, ruil type: "string" in voor type: "integer" op de enum-entry.

Hoe handelt het map<K, V> af?

Rendert als { "type": "object", "additionalProperties": <V-schema> }. JSON-object-keys zijn altijd strings, dus een proto-map met een niet-string key (bijv. map<int32, string>) krijgt een description-note die uitlegt dat de runtime-keys naar string gecoerced worden. Het value-schema volgt dezelfde type-mapping-regels als een gewoon field.

Worden fields als required gemarkeerd?

Nee — proto3-fields hebben in het wire format altijd een default en zijn altijd aanwezig in de JSON-uitvoer (met lege defaults als "", 0, false, [], {}), dus het schema lijst niets onder required. Als je echt wilt dat een field required is bij validatie, voeg het handmatig toe aan een required-array op de parent-message. proto3 optional-fields en oneof worden ook niet als oneOf afgedwongen in de uitvoer — dat zijn runtime-semantieken die JSON Schema niet volledig kan uitdrukken zonder extra annotaties.

Hoe worden geneste messages gerefereerd?

Elke message en enum wordt opgehesen naar een platte $defs-blok, geïndexeerd op leaf-naam. Field-referenties gaan via $ref: "#/$defs/MessageName". Plat maken houdt het document compact en zorgt dat dubbel geneste types niet gedupliceerd worden. Als twee messages in verschillende packages een leaf-naam delen, houdt de converter de eerste definitie aan — splits conflicterende namen voor het plakken als dat ertoe doet.

Kan ik dit direct in Ajv steken?

Ja. ajv.compile(schema) op de uitvoer werkt out-of-the-box zodra Ajv geconfigureerd is voor draft 2020-12 (new Ajv2020() uit ajv/dist/2020). De $ref-entries lossen intern op omdat alles in hetzelfde document staat. Als je format-validatie wilt (date-time, duration), voeg ajv-formats ernaast toe.

Gerelateerde tools

Als je met Protobuf, JSON Schema en validatie in de weer bent, passen deze goed bij elkaar: