Inndata (.proto-skjema)

Utdata (Java)

Hva dette verktøyet gjør

Du har et Protocol Buffers-skjema og en Java-tjeneste som konsumerer disse meldingene — kanskje over gRPC, kanskje via JSON over HTTP. Å kjøre den offisielle protoc med Java-pluginen gir deg genererte klasser i Builder-stil — flotte for produksjon, men tunge når du skisserer, prototyper eller hånd-mapper JSON ned i en POJO. Denne konverteren spytter ut vanlige Java-klasser — public-felter, fornuftige defaults, én klasse per melding, separate typer for enums.

Typetilordningen følger det håndskrevet Java ser ut som i praksis: stringString, boolboolean, int32/sint32/sfixed32int, int64/sint64/sfixed64long, doubledouble, floatfloat, bytesbyte[]. Java har ingen unsigned numeriske typer, så uint32/fixed32 faller til int og uint64/fixed64 faller til long — greit for de fleste bruksområder; trenger du faktisk den øverste biten, bruk Integer.toUnsignedLong ved grensen. repeated T blir List<T>, map<K, V> blir Map<K, V>, begge fra java.util.

Feltnavn konverteres fra snake_case (Protobuf-konvensjon) til camelCase (Java-konvensjon) — i tråd med det protoc ville gjort, og det proto3 JSON-tilordningen bruker. Enums blir til top-level public enum-typer med heltallsverdien fra wire bevart som et final-felt, slik at du kan round-trippe gjennom protoc-generert kode hvis du noen gang bytter over. Nestede meldinger flates ut til top-level klasser, slik at hver kan flytte inn i sin egen fil når du deler opp utdata. Alt kjører i nettleseren din — skjemaet ditt forlater ikke siden.

Slik bruker du det

Tre steg. Utdata er klar til å slippes inn i et Java-prosjekt.

1

Lim inn .proto-skjemaet ditt

Slipp skjemaet i den venstre editoren. syntax = "proto3"; på toppen er greit men valgfritt. Parseren håndterer nestede message-blokker, enum-deklarasjoner, oneof, map<K, V> og feltvalg. import-direktiver gjenkjennes men hoppes over — lim inn importerte typer inline hvis du trenger dem.

Feltnavnkonvertering skjer automatisk: order_id i .proto blir orderId i Java. Meldings- og enumnavn beholdes som de er (allerede PascalCase).

2

Les utdata

Til høyre: én enkelt .java-blokk med alle enums først, deretter alle klasser i deklarasjonsrekkefølge. Hver klasse har public-felter med default-verdier for primitiver (0, 0.0, false, ""), og referansetyper (List, Map, meldingsreferanser) står som null til du fyller dem. Importene java.util.List og java.util.Map legges kun til når skjemaet trenger dem.

3

Slipp inn i prosjektet ditt

Kopier hver klasse til sin egen .java-fil (Java krever én public-klasse per fil). Legg til en package-deklarasjon, og koble så klassene til JSON-deserializeren etter eget valg — Jackson plukker opp public-felter som standard, og proto3 JSON-tilordningen bruker camelCase, så feltnavnene matcher allerede. Foretrekker du gettere/settere, klarer IntelliJ sin "Encapsulate Fields"-refaktor det med ett tastetrykk.

Når det faktisk sparer tid

Skissere en Java-klient mot en gRPC-tjeneste

Du gjør en spike med en Java-klient mot en eksisterende gRPC-backend — kanskje en Spring Boot-tjeneste, kanskje en Quarkus — og du vil ikke sette opp den fulle protoc Maven- eller Gradle-pluginen ennå. Lim inn skjemaet, slipp klassene i src/main/java/dto, deserialiser JSON-svaret med Jackson, send prototypen.

Håndlage DTO-er som matcher en proto

Teamet ditt bruker Protobuf som sannhetskilde på wire, men den konsumerende Java-tjenesten trenger bare tre eller fire felter, og du vil ikke ha en Message/Builder-avhengighet. Lim inn skjemaet, slett feltene du ikke trenger, og du har en vanlig DTO som kompilerer frittstående.

Gjennomgå en Protobuf-API-endring

En backend-kollega la til felter i en melding. Du vil se hvordan det påvirker Java-POJO-en uten å kjøre byggingen. Lim inn det nye .proto, diff Java-utdata mot dine nåværende klasser, legg igjen en fokusert gjennomgangskommentar.

Kryssjekke utdata fra protoc

Byggingen din bruker den offisielle protoc Java-pluginen, som produserer klasser i Builder-stil. Lim inn skjemaet her for en ren referanse på hvordan vanlig Java ser ut — nyttig for dokumentasjon, onboarding eller for Kotlin-kolleger som foretrekker data classes.

Vanlige spørsmål

Sendes skjemaet mitt noe sted?

Nei. Parseren og Java-emitteren kjører helt i nettleseren din som JavaScript. Åpne DevTools og se på Network-fanen mens du limer inn — null requests. Nyttig når skjemaet inneholder interne pakkestier, typenavn eller noe annet du helst ikke vil sende til en tredjepartstjeneste.

Hvorfor public-felter og ikke gettere/settere?

To grunner. For det første er utdata ment som et utgangspunkt du tilpasser — public-felter er det minste som kompilerer, og du kan alltid kjøre "Encapsulate Fields" i IDE-en din. For det andre er den vanligste konsumenten Jackson-deserialisering, som virker rett på public-felter. Trenger du en record, en uforanderlig type eller en Lombok @Data-klasse, lim inn utdata og refaktorer.

Hvordan håndteres uint32 og uint64?

Java har ingen unsigned heltallstyper, så uint32/fixed32 tilordnes int og uint64/fixed64 til long. For verdier som ligger innenfor det signed-intervallet, fungerer det greit; for verdier over Integer.MAX_VALUE eller Long.MAX_VALUE ser du negative tall. Standardløsningen er Integer.toUnsignedLong(x) ved grensen, eller bruk aritmetiske helpers fra java.lang.Long — se Java 21 API-dokumentasjonen for unsigned-helpers.

Hvorfor er int64-felter bare long, ikke String?

TypeScript og JSON har et presisjonstak på 53 bit, så proto3 JSON-spec-en koder 64-bits heltall som strings for å bevare presisjonen. Javas long er et ekte 64-bits signed heltall uten presisjonstap, så vi beholder Java-typen som long. Hvis du deserialiserer JSON der serveren allerede har kodet int64 som streng, konfigurer Jackson med @JsonFormat eller en custom deserializer; den underliggende typen trenger ikke å endres.

Hvordan håndteres nestede meldinger?

Hver nestet melding flates ut til en top-level klasse. Java-konvensjonen er én public-klasse per fil, så flate top-level typer er enklere å dele opp når du kopierer hver klasse til sin egen .java-fil. Vil du heller ha statiske indre klasser (stilen protoc spytter ut), lim inn utdata og flytt de nestede klassene inn i forelderen sin — feltreferansene bruker allerede leaf-navnet og resolver så snart de havner i samme scope.

Er felter merket som optional?

Nei — proto3-felter har alltid en default i wire-formatet, så primitive felter initialiseres til Java-nullverdien sin (0, 0.0, false, ""). Referansetyper (List, Map, nestede meldinger, byte[]) starter som null; husk å initialisere dem før du legger til elementer. Vil du ha eksplisitte Optional<T>-wrappere, er det et manuelt steg.

Håndterer den oneof?

Hvert oneof-felt sendes ut som et vanlig klassefelt. Utdata håndhever ikke "nøyaktig én"-betingelsen som oneof innebærer — for det ville du trengt et sealed type-hierarki eller en runtime-sjekk, og ingen av delene passer en vanlig POJO. Vil du ha strammere modellering, ta utdata og konverter oneof-feltene til et sealed interface med én record per tilfelle.

Kan jeg bruke disse klassene med den offisielle protobuf-java-runtimen?

Ikke direkte — den offisielle runtimen forventer klasser generert av protoc med Builder, parseFrom og resten av com.google.protobuf.MessageOrBuilder-kontrakten. Klassene fra dette verktøyet er vanlige POJO-er, ment for JSON-serialisering (Jackson, Gson, Moshi). For binært wire-format vil du fortsatt ha den offisielle codegen — se Java-tutorialen for oppsettet.

Relaterte verktøy

Hvis du jobber med Protobuf, JSON og Java, passer disse godt sammen: