Protobuf'tan JSON Schema'ya Dönüştürücü
Bir .proto şeması yapıştır. Her message ve enum için bir $defs girdisine sahip JSON Schema 2020-12 dökümanı al; Ajv veya herhangi bir modern doğrulayıcıya hazır.
Girdi (.proto şeması)
Çıktı (JSON Schema)
Bu araç ne yapar
Elinde bir Protocol Buffers şeması ve JSON yutan bir servis var — belki bir webhook handler’ı, belki HTTP transcoding yapan bir gRPC gateway, belki kod’una ulaşmadan önce doğrulama yapan bir API gateway. Proto’yu yansıtan bir JSON Schema dökümanı istiyorsun — gelen payload’ları doğrulamak, OpenAPI parçaları üretmek veya yapılandırılmış çıktı prompt’larına vermek için. Bu dönüştürücü bunu tarayıcında yapar — .proto’yu yapıştır, JSON Schema’yı kopyala, doğrulayıcı konfigürasyonuna bırak.
Çıktı JSON Schema draft 2020-12 — Ajv dahil her modern doğrulayıcının desteklediği güncel draft. Her message $defs altında type: "object" ve properties haritası olan bir girdiye dönüşür. Her enum type: "string" ve enum altında listelenmiş değer adlarıyla bir $defs girdisi olur — proto3’ün JSON’da enum’ları ada göre serileştirme biçimine uygun. Field referansları leaf adı kullanılarak $ref: "#/$defs/MessageName" ile çözülür, böylece iç içe tipler okunur kalır.
Tip eşlemesi proto3 JSON eşleme spec’ini takip eder. string/bool doğrudan eşleşir. 32 bit int’ler type: "integer" ve format: "int32" alır; unsigned 32 bit’ler minimum: 0 ekler. 64 bit int’ler type: "string" ve format: "int64" ile bir sayısal pattern alır, çünkü JSON Number’lar 2^53’ün üzerinde hassasiyet kaybeder ve proto3 64 bit egé sayıları wire üzerinde tırnaklı string olarak kodlar. bytes contentEncoding: "base64" ile bir string’e dönüşür. google.protobuf.Timestamp gibi well-known tipler RFC 3339’a göre format: "date-time"’a eşlenir. Dönüşüm tamamen tarayıcında çalışır — şemanla sayfa dışına çıkmaz.
Nasıl kullanılır
Üç adım. Çıktı, doğrudan bir doğrulayıcıya verebileceğin tek bir JSON Schema dökümanı.
.proto şemanı yapıştır
Şemayı sol editöre bırak. Üstteki syntax = "proto3"; sorun değil ama opsiyonel. Parser iç içe message bloklarını, enum bildirimlerini, oneof, map<K, V> ve field option’larını ele alır. import direktifleri tanınır ama atlanır — gerekirse import edilen tipleri inline yapıştır.
Field adları snake_case olarak kalır (proto3 JSON encoder’ın varsayılan olarak yaydığıyla uyumlu — dönüşüm yok). Client’ın preserve_proto_field_names = false ayarlıysa, property anahtarlarını elle camelCase’e çevir.
Şemayı oku
Sağda: $id, title, son bildirilen kök message’ı gösteren üst düzey bir $ref ve dosyadaki her message ve enum’u tutan bir $defs bloğu içeren bir JSON Schema 2020-12 dökümanı. Her message properties haritasıyla bir nesne şemasına, her enum değer adlarını taşıyan bir string şemasına dönüşür. $ref veya $defs anlambilimini hatırlamak istersen Understanding JSON Schema rehberini oku.
Bir doğrulayıcıya bağla
Çıktıyı schema.json olarak kaydet, Ajv (Node) veya jsonschema (Python) ya da stack’ının kullandığı doğrulayıcıya yükle, sonra gRPC gateway’in veya webhook’unun aldığı JSON’a karşı çalıştır. Uyuşmazlıklar /items/0/sku must be string gibi okunabilir hata yolları olarak görünür. Aynı şema OpenAPI 3.1 component tanımlarını veya bir LLM için yapılandırılmış çıktı prompt’larını da besleyebilir.
Gerçekten zaman kazandırdığı yerler
proto’da tanımlı webhook’ları doğrulama
Takımın bir OrderShipped olayı için Protobuf’ı gerçeklik kaynağı olarak kullanıyor ama asıl webhook alıcısı JSON alıyor — alıcı tarafında proto runtime yok. .proto’yu yapıştır, JSON Schema’yı Ajv’ye düşür ve iş mantığına ulaşmadan önce edge’de bozuk payload’ları reddet. quantity’si eksik bir SKU-101 artık veritabanına asla ulaşmaz.
gRPC şemalarından OpenAPI 3.1 oluşturma
Bir gRPC-gateway için OpenAPI 3.1 spec’leri yazıyorsun. OpenAPI 3.1 JSON Schema 2020-12 ile uyumlu, dolayısıyla buradaki $defs bloğu küçük bir yeniden adlandırma sonrası doğrudan components.schemas altına düşer. protoc-gen-openapi plugin’i kurmaya yok, Buf CLI ayarlamaya yok — sadece yapıştır, düzenle, commit’le.
proto’dan LLM yapılandırılmış çıktı
OpenAI veya Anthropic’in mevcut .proto’nla eşleşen tipli bir Order nesnesi döndürmesini istiyorsun. Şemayı yapıştır, $defs/Order girdisini al ve response_format’ın JSON Schema’sı olarak geçir. Model artık elle dönüştürmeye gerek bırakmadan gRPC servisinde gidip dönen çıktı üretir.
Bir Protobuf API değişikliğini reviewlamak
Bir backend takım arkadaşı Address’e iki field ekledi ve bir enum değerini yeniden adlandırdı. Tüm codegen pipeline’ını çalıştırmadan bunun gateway’inin kullandığı JSON Schema’yı nasıl etkilediğini görmek istiyorsun. Yeni .proto’yu yapıştır, şemayı commit’li kopyana karşı diff’le, PR’a odaklı bir review yorumu bırak.
Sık sorulan sorular
Şemam bir yere gönderiliyor mu?
Hayır. Parser ve JSON Schema yayıcı tamamen tarayıcında JavaScript olarak çalışır. Yapıştırırken DevTools’u açıp Network sekmesini izle — sıfır istek. Şemanın içinde dahili package yolları, tip adları veya üçüncü taraf bir servise vermek istemediğin bir şey varsa kullanışlı.
Çıktı hangi JSON Schema draft’ını hedefliyor?
Draft 2020-12, mevcut yayınlanmış draft. Her çıktı dökümanındaki $schema URI’ı https://json-schema.org/draft/2020-12/schema. 2019-09’dan sonra ne değiştiği için 2020-12 release notes’ına bak. Aktif olarak bakılan her doğrulayıcı (Ajv 8+, Python için jsonschema 4+, NJsonSchema, Java için Justify) varsayılan olarak 2020-12’yi destekler.
Neden int64 fieldları integer değil de string?
Çünkü proto3 JSON eşleme spec’i böyle söylüyor ve haklı. JSON Number’lar IEEE-754 double’dır ve 2^53’ün üzerinde hassasiyet kaybeder. Gerçek bir int64 bu tavanın çok ötesinde değerler taşıyabilir — sipariş ID’leri, nano cinsinden timestamp’lar, ledger bakiyeleri — bu yüzden proto3 64 bit egé sayıları tırnaklı JSON string’leri olarak kodlar. Şema bunu type: "string", format: "int64" ve bir sayısal pattern’la yansıtır, böylece bir doğrulayıcı hala "abc"’yi reddeder. Sunucun 64 bit int’leri ham JSON Number olarak veriyorsa (bazı legacy gateway’ler bunu yapar), o girdileri elle { "type": "integer" }’a çevir.
Neden enum’lar integer değil de string?
Aynı sebep — proto3’ün varsayılan JSON kodlaması bu. Enum’lar wire sayısı olan integer (2) yerine değer adları ("ORDER_STATUS_PAID") olarak serileşir. Bu JSON payload’larını okunabilir, şemayı daha basit yapar. Tamsayı numaralar wire format meselesi, doğrulama meselesi değil; o yüzden JSON Schema’da yoklar. Int yayan varsayılan dışı bir encoder yapılandırdıysan, enum girdisindeki type: "string"’ı type: "integer" ile değiştir.
map<K, V>’yi nasıl ele alıyor?
{ "type": "object", "additionalProperties": <V-schema> } olarak render eder. JSON nesne anahtarları her zaman string olduğundan, string olmayan anahtara sahip bir proto map (örn. map<int32, string>) için runtime anahtarlarının string’e zorlanacağını açıklayan bir description notu eklenir. Değer şeması normal bir field ile aynı tip eşleme kurallarını takip eder.
Field’lar required olarak işaretleniyor mu?
Hayır — proto3 field’larının wire format’ta her zaman bir varsayılanı vardır ve JSON çıktısında her zaman mevcuttur ("", 0, false, [], {} gibi boş varsayılanlarla), bu yüzden şema required altında hiçbir şey listelemez. Bir field’ın doğrulama zamanında gerçekten required olmasını istiyorsan, parent message’ın required dizisine elle ekle. proto3’ün optional field’ları ve oneof da çıktıda oneOf olarak zorlanmaz — onlar JSON Schema’nın ekstra annotation olmadan tam olarak ifade edemeyeceği runtime semantikleridir.
İç içe message’lar nasıl referans alınıyor?
Her message ve enum, leaf adıyla anahtarlanmış düz bir $defs bloğuna kaldırılır. Field referansları $ref: "#/$defs/MessageName" üzerinden gider. Düzleştirmek dökümanı kompakt tutar ve iki kez iç içe tiplerin çoğaltmasını önler. Farklı package’lardaki iki message bir leaf adını paylaşıyorsa, dönüştürücü ilk tanımı tutar — önemliyse yapıştırmadan önce çatışan adları ayır.
Bunu doğrudan Ajv’ye sokabilir miyim?
Evet. Ajv draft 2020-12 için yapılandırıldığı zaman (ajv/dist/2020’dan new Ajv2020()) çıktı üzerinde ajv.compile(schema) kutudan çıkar çıkmaz çalışır. Her şey aynı dökümanda olduğundan $ref girdileri dahili olarak çözülür. Format doğrulaması (date-time, duration) istiyorsan yanına ajv-formats’ı ekle.
İlgili araçlar
Protobuf, JSON Schema ve doğrulamayla cebelleşiyorsan bunlar iyi tamamlar: