Protobuf till JSON Schema-konverterare
Klistra in ett .proto-schema. Få ett JSON Schema 2020-12-dokument med en $defs-post per message och enum, klart för Ajv eller vilken modern validator som helst.
Indata (.proto-schema)
Utdata (JSON Schema)
Vad det här verktyget gör
Du har ett Protocol Buffers-schema och en tjänst som tar emot JSON — kanske en webhook-handler, kanske en HTTP-transcoded gRPC-gateway, kanske en API-gateway som validerar requesten innan den når din kod. Du vill ha ett JSON Schema-dokument som speglar proton för att validera inkommande payloads, generera OpenAPI-fragment eller mata in det i prompts för structured output. Den här konverteraren gör det i din webbläsare — klistra in .proto, kopiera JSON Schema, lägg in det i validatorns config.
Utdatan är JSON Schema draft 2020-12 — den nuvarande draften, som stöds av varje modern validator inklusive Ajv. Varje message blir en post under $defs med type: "object" och en properties-map. Varje enum blir en $defs-post med type: "string" och värdenamnen listade under enum — i linje med hur proto3 serialiserar enums efter namn i JSON. Fältreferenser löser via $ref: "#/$defs/MessageName" med leaf-namnet, så nästlade typer förblir läsbara.
Typmappningen följer specen för proto3-JSON-mappning. string/bool mappar direkt. 32-bitars ints får type: "integer" med format: "int32"; unsigned 32-bit lägger till minimum: 0. 64-bitars ints blir type: "string" med format: "int64" och ett numeriskt pattern, eftersom JSON Numbers tappar precision över 2^53 och proto3 kodar 64-bitars heltal som citerade strings på wiren. bytes blir en string med contentEncoding: "base64". Well-known-typer som google.protobuf.Timestamp mappar till format: "date-time" enligt RFC 3339. Konverteringen körs helt i din webbläsare — ditt schema lämnar inte sidan.
Så använder du det
Tre steg. Utdatan är ett enda JSON Schema-dokument som du kan ge direkt till en validator.
Klistra in ditt .proto-schema
Släpp schemat i editorn till vänster. syntax = "proto3"; i toppen är okej men frivilligt. Parsern hanterar nästlade message-block, enum-deklarationer, oneof, map<K, V> och fältoptioner. import-direktiv känns igen men hoppas över — klistra in importerade typer inline om du behöver dem.
Fältnamn stannar i snake_case (i linje med vad proto3 JSON-encodern spottar ut som standard — ingen transformation). Om din klient sätter preserve_proto_field_names = false, byt property-nycklarna till camelCase för hand.
Läs schemat
Till höger: ett JSON Schema 2020-12-dokument med $id, title, en top-level $ref som pekar på din senast deklarerade rot-message, och ett $defs-block som håller varje message och enum från filen. Varje message blir ett objektschema med en properties-map; varje enum blir ett string-schema med värdenamnen. Läs guiden Understanding JSON Schema om du behöver en uppdatering på $ref- eller $defs-semantiken.
Koppla in det i en validator
Spara utdatan som schema.json, ladda in den i Ajv (Node) eller jsonschema (Python) eller den validator din stack använder, och kör den sedan mot JSON:en som din gRPC-gateway eller webhook tar emot. Avvikelser kommer ut som läsbara felvägar typ /items/0/sku must be string. Samma schema kan också mata komponentdefinitioner i OpenAPI 3.1 eller prompts för structured output till en LLM.
När det faktiskt sparar tid
Validera webhooks definierade i proto
Ditt team använder Protobuf som källa till sanning för en OrderShipped-händelse, men den faktiska webhook-mottagaren får JSON — det finns ingen proto-runtime på mottagarsidan. Klistra in .proto, släpp JSON Schema i Ajv och avvisa felaktiga payloads vid kanten innan de når affärslogiken. En SKU-101 med saknad quantity kommer aldrig till databasen.
Bygga OpenAPI 3.1 från gRPC-scheman
Du skriver OpenAPI 3.1-specs för en gRPC-gateway. OpenAPI 3.1 är JSON Schema 2020-12-kompatibel, så $defs-blocket här ramlar rakt under components.schemas efter en liten omdöpning. Inget protoc-gen-openapi-plugin att installera, ingen Buf CLI att sätta upp — bara klistra, redigera, committa.
LLM structured outputs från ett proto
Du vill att OpenAI eller Anthropic ska returnera ett typat Order-objekt som matchar ditt befintliga .proto. Klistra in schemat, ta posten $defs/Order och skicka in den som JSON Schema i response_format. Modellen producerar nu output som gör round-trip genom din gRPC-tjänst utan manuell coercion.
Granska en Protobuf-API-ändring
En backend-kollega lade till två fält i Address och döpte om ett enum-värde. Du vill se hur det påverkar JSON Schema som din gateway använder utan att köra hela codegen-pipelinen. Klistra in det nya .proto, diffa schemat mot din committade kopia, lämna en fokuserad granskningskommentar på PR:en.
Vanliga frågor
Skickas mitt schema någonstans?
Nej. Parsern och JSON Schema-emittern körs helt i din webbläsare som JavaScript. Öppna DevTools och titta på Network-fliken medan du klistrar — noll requests. Användbart när schemat innehåller interna package-paths, typnamn eller något du inte vill överlämna till en tredjepartstjänst.
Vilken JSON Schema-draft riktar utdatan in sig på?
Draft 2020-12, den nuvarande publicerade draften. $schema-URI:n i varje utdatadokument är https://json-schema.org/draft/2020-12/schema. Se 2020-12 release notes för vad som ändrats sedan 2019-09. Varje aktivt underhållen validator (Ajv 8+, jsonschema 4+ för Python, NJsonSchema, Justify för Java) stödjer 2020-12 som standard.
Varför är int64-fält strings, inte integers?
För det är vad specen för proto3-JSON-mappning säger, och den har rätt. JSON Numbers är IEEE-754-doubles, som tappar precision över 2^53. En riktig int64 kan bära värden långt över det taket — order-ID:n, timestamps i nanos, ledger-saldon — så proto3 kodar 64-bitars heltal som citerade JSON-strings. Schemat speglar det med type: "string", format: "int64" och ett numeriskt pattern så att en validator fortfarande avvisar "abc". Om din server skickar ut 64-bitars ints som råa JSON Numbers (vissa legacy-gateways gör det), ändra de posterna till { "type": "integer" } för hand.
Varför är enums strings, inte integers?
Samma anledning — det är proto3:s default JSON-encoding. Enums serialiseras som sitt värdenamn ("ORDER_STATUS_PAID") snarare än det heltaliga wire-numret (2). Det gör JSON-payloads läsbara och schemat enklare. Heltalsnumren finns inte i JSON Schema eftersom de är en wire-format-fråga, inte en valideringsfråga. Om du har en icke-default encoder konfigurerad att skicka ints, byt type: "string" mot type: "integer" på enum-posten.
Hur hanterar den map<K, V>?
Renderar som { "type": "object", "additionalProperties": <V-schema> }. JSON-objektnycklar är alltid strings, så en proto-map med en icke-string-nyckel (t.ex. map<int32, string>) får en description-not som förklarar att runtime-nycklarna kommer att string-coercas. Värdeschemat följer samma typmappningsregler som ett vanligt fält.
Är fält markerade som required?
Nej — proto3-fält har alltid en default i wire-formatet och är alltid närvarande i JSON-utdatan (med tomma defaults som "", 0, false, [], {}), så schemat listar inget under required. Om du faktiskt vill att ett fält ska vara required vid validering, lägg till det i en required-array på parent-messaget för hand. proto3 optional-fält och oneof framtvingas inte heller som oneOf i utdatan — det är runtime-semantik som JSON Schema inte kan uttrycka fullt utan extra annotationer.
Hur refereras nästlade messages?
Varje message och enum hissas upp till ett platt $defs-block nycklat efter sitt leaf-namn. Fältreferenser går via $ref: "#/$defs/MessageName". Att platta till håller dokumentet kompakt och betyder att dubbelt nästlade typer inte dupliceras. Om två messages i olika packages delar leaf-namn behåller konverteraren den första definitionen — separera kolliderande namn innan du klistrar in om det spelar roll.
Kan jag stoppa in detta direkt i Ajv?
Ja. ajv.compile(schema) på utdatan funkar direkt så fort Ajv är konfigurerat för draft 2020-12 (new Ajv2020() från ajv/dist/2020). $ref-posterna löser internt eftersom allt ligger i samma dokument. Vill du ha format-validering (date-time, duration), lägg till ajv-formats bredvid.
Relaterade verktyg
Om du brottas med Protobuf, JSON Schema och validering passar dessa bra ihop: