The registry treats Protobuf and JSON Schema the same way; a schemaType field says which parser to use, and Avro 129 is the default when it is absent. This script writes the event in both and registers it:
# The same event as Protobuf and as JSON Schema; schemaType tells the registry the format
cat > schemas/order_event.proto <<'PROTO'
syntax = "proto3";
package booknest.v1;
message OrderEvent {
int64 event_id = 1; int64 ts_millis = 2; string type = 3; int64 order_id = 4;
optional int64 customer_id = 5; optional double total = 6;
}
PROTO
cat > schemas/order_event.schema.json <<'JSON'
{"$schema": "http://json-schema.org/draft-07/schema#", "title": "OrderEvent", "type": "object",
"properties": {"event_id": {"type": "integer"}, "ts": {"type": "string", "format": "date-time"},
"type": {"type": "string"}, "order_id": {"type": "integer"},
"customer_id": {"type": "integer"}, "total": {"type": "number"}},
"required": ["event_id", "ts", "type", "order_id"]}
JSON
R=localhost:33081
for f in proto:PROTOBUF:order_event.proto jsonschema:JSON:order_event.schema.json; do
IFS=: read -r name type file <<< "$f"
jq -n --arg t $type --rawfile s schemas/$file '{schemaType: $t, schema: $s}' |
curl -s -X POST -H 'Content-Type: application/vnd.schemaregistry.v1+json' -d @- \
$R/subjects/booknest.order-events-$name-value/versions >/dev/null
done
curl -s "$R/schemas?latestOnly=true" | jq -r '.[] | "\(.id) \(.schemaType // "AVRO") \(.subject)"'Output
1 AVRO booknest.order-events-avro-value 3 JSON booknest.order-events-jsonschema-value 2 PROTOBUF booknest.order-events-proto-value
IDs are global across formats. Protobuf's serializer adds message indexes after the ID, and removed field numbers must never be reused; JSON Schema stays readable but large. Imports of your own .proto files become schema references.