JSON to Protobuf

Draft a .proto schema from a sample payload, with one message per object shape and field numbers already assigned.

JSON
Proto schema
Runs locally in your browser

About the JSON to Protobuf

Moving a JSON service onto gRPC starts with a schema, and typing it out from a sample response is tedious. This generator reads the payload and writes proto messages: one per object shape, fields numbered from one in the order they appear, repeated fields for arrays and a nested message for every inner object.

Scalar mapping is a judgement call, so it is exposed as an option. Whole numbers default to int64 because JSON has no integer width and a value that fits in 32 bits today may not tomorrow; switch to int32 when you know the range. Decimals default to double for the same reason. Nulls and mixed type fields become google.protobuf.Value, and the import for struct.proto is added automatically when that happens.

Field names are converted to snake case because that is what the style guide asks for, and protoc derives the JSON name from it. When that derived name would not match your original key, a json_name option is emitted on the field so the wire format keeps matching the existing API. Selecting proto2 adds the required and optional labels that syntax demands.

Treat the result as a first draft. Field numbers are assigned in document order, and once a schema ships those numbers must never be reused, so review them before committing. For a validation schema instead of a wire format, see JSON to JSON Schema.

How to use

  1. Paste a representative payload, or press Sample to load a sensor report.
  2. Name the root message and, if you use one, the package.
  3. Choose the integer and decimal widths that match your data.
  4. Copy the schema or download schema.proto, then review the field numbers before committing.

Common questions

Are the field numbers safe to keep?
They are assigned in document order as a starting point. Field numbers are part of the wire contract forever, so review them before the schema is published.
Why did my null field become google.protobuf.Value?
Proto has no untyped null, so a field with no observable type falls back to Value and the struct.proto import is added for you.
What is the json_name option for?
It keeps the JSON representation matching your original key after the field name was converted to snake case, so an existing client keeps working.
Can it produce proto2?
Yes. Switch the syntax selector and every field gains the required or optional label that proto2 needs, based on whether the sample ever showed it as null.