100 % local — vos données ne quittent jamais votre navigateur

JSON en Protobuf — un .proto que protoc compile

Transformez un échantillon JSON en messages proto3. Les noms sont réparés pour protobuf et json_name garde la clé d’origine : les deux bords s’entendent.

Instantané Privé Zéro cookie

Entrée JSON

Sortie Protobuf

Ce que fait cet outil

Un échantillon JSON devient des messages proto3, un par objet.

{ "id": 1, "name": "Ada", "tags": ["admin"], "address": { "city": "Paris" } }
syntax = "proto3";

message Root {
  int64 id = 1;
  string name = 2;
  repeated string tags = 3;
  Address address = 4;
}

message Address {
  string city = 1;
}

Les numéros de champs partent de 1 dans chaque message, dans l’ordre d’apparition des clés. C’est eux que protobuf met sur le fil : les noms sont pour les humains, les numéros sont le contrat.

La clé d’origine est conservée

Un nom de champ protobuf s’écrit par convention [a-z_][a-z0-9_]* et n’admet pas de tiret. content-type devient donc content_type — et voici ce qui mord : le mappage JSON de proto3 dérive la clé JSON du nom de champ, en lowerCamelCase. content_type devient contentType, qui n’est pas la clé de vos données.

string content_type = 1 [json_name = "content-type"];

json_name fixe la clé d’origine, et le message relit le document dont il vient. L’option n’est émise que si la réparation a changé quelque chose : une clé déjà en snake_case n’en a pas besoin, un analyseur proto3 acceptant aussi le nom de champ tel quel.

C’était un vrai défaut : le .proto engendré cessait en silence de correspondre à sa propre entrée. Trouvé en écrivant cette page, puis corrigé.

Les entiers 64 bits voyagent en chaînes

Les entiers deviennent int64. Dans le mappage JSON de proto3, int64 est encodé en chaîne :

{ "id": "12345678901" }

C’est la spécification, pas un choix d’ici — les nombres JSON ne portent pas 64 bits sans risque, le mappage les contourne. Cela signifie qu’un aller-retour par protobuf change le type que voit votre consommateur. Si le champ est un petit compteur, passer à int32 est une retouche qui se justifie.

Ce que proto3 ne sait pas dire, il le dit avec Value

  • null et les valeurs inconnues deviennent google.protobuf.Value, et import "google/protobuf/struct.proto" est ajouté — seulement si quelque chose en a besoin.
  • Un tableau imbriqué devient google.protobuf.ListValue : proto3 interdit repeated repeated, un tableau de tableaux n’a donc pas de forme directe.
  • Un tableau hétérogène devient repeated google.protobuf.Value, sauf s’il mêle entiers et flottants : repeated double couvre alors les deux.

La présence n’est pas ce qu’on croit

En proto3, un champ scalaire sans mot-clé optional n’a pas de présence : après décodage, un champ absent et un champ à 0, "" ou false sont indiscernables. Rien dans un échantillon JSON ne dit quelles clés sont vraiment optionnelles, donc rien ici n’est marqué optional. Là où la différence compte — une note nullable, un drapeau non renseigné — ajouter le mot-clé est la retouche à faire.

Confidentiel par conception

Tout s’exécute localement dans votre navigateur en JavaScript. Vos données ne sont jamais envoyées sur un serveur, ce qui rend l’outil sûr pour des contenus sensibles, et il fonctionne hors ligne.

Questions fréquentes

Pourquoi certains champs portent-ils `[json_name = "…"]` ?
Parce que leur nom a dû changer. Un nom de champ protobuf n’admet pas de tiret : `content-type` devient `content_type` — et le mappage JSON de proto3 cherche alors `contentType`, pas la clé que vous avez. `json_name` fixe l’original. Sans lui, le message ne relit plus le JSON dont il vient ; c’était un vrai défaut, corrigé.
Pourquoi mes entiers 64 bits sont-ils des chaînes dans le JSON de sortie ?
C’est le mappage JSON de proto3, pas cet outil : `int64`, `uint64` et `fixed64` sont encodés en chaînes, les nombres JSON ne portant pas 64 bits sans risque. Votre `{"id": 12345678901}` devient `{"id": "12345678901"}` après un aller-retour par protobuf. Bon à savoir avant qu’un client d’en face s’y étrangle.
Puis-je modifier les numéros de champs ?
Oui, mais renuméroter un message existant casse la compatibilité avec les données déjà encodées : c’est le numéro, pas le nom, qui circule. Ceux d’ici partent de 1 dans chaque message, ce qui convient à une définition neuve. Pour un message déjà en production, gardez les numéros existants et donnez aux nouveaux champs des numéros libres.

Convertisseurs associés