Skip to content
Back to Blog
jsongolangcode-generationdeveloper-tools

JSON in Go-Struct konvertieren: Ein praktischer Leitfaden

Das manuelle Erstellen von Go-Structs aus API-JSON ist fehleranfällig: falsche Typen, fehlende Tags, kaputte Verschachtelung. Dieser Leitfaden erklärt, wie Generatoren Typen ableiten und wie Sie JSON in einem Klick in ein Go-Struct konvertieren.

SZ
Founder, Molixa
13 min read
Teilen
JSON in Go-Struct konvertieren: Ein praktischer Leitfaden
Table of contents7 sections

Die Konvertierung von JSON in eine Go-Struktur bedeutet, eine JSON-Beispielnutzlast in einen Go-Typ mit den richtigen Feldtypen, exportierten Namen und json:-Tags umzuwandeln, sodass Sie sauber Unmarshal darauf anwenden können. Ein Generator macht dies, indem er den Wert jedes Schlüssels untersucht und einen Go-Typ ableitet, dann den JSON-Schlüsselnamen in einen PascalCase-exportierten Feldnamen mit einem passenden Tag umwandelt. Diese Anleitung zeigt genau, wie diese Ableitung funktioniert, wo sie schiefgeht und wie Sie eine korrekte Struktur erhalten, ohne eine einzige Klammer von Hand zu tippen.

Die meisten Entwickler stoßen auf dasselbe Problem: Eine API gibt ein JSON-Objekt mit 40 Schlüsseln zurück, und das manuelle Schreiben der passenden Struktur ist langsam und fehleranfällig. Sie vergessen ein Tag, raten int, wo die API eine Gleitkommazahl sendet, oder glätten ein verschachteltes Objekt, das ein eigener Typ sein sollte. Das Ergebnis ist ein Laufzeit-Unmarshal, der Felder stillschweigend verwirft. Die Lösung besteht darin, die Regeln zu verstehen, die ein Konverter anwendet, damit Sie seiner Ausgabe vertrauen und die Fälle korrigieren können, die er nicht erraten kann.

Wie ein JSON-zu-Go-Struct-Konverter Typen ableitet#

Ein Konverter durchläuft JSON Wert für Wert. JSON hat nur sechs Werttypen (String, Zahl, Boolean, Objekt, Array, null), aber Go hat viele. Die Zuordnung ist größtenteils deterministisch, mit zwei wirklich mehrdeutigen Fällen, die Sie kennen sollten.

Hier ist die Kernzuordnung, die jeder Generator verwendet:

JSON-WertAbgeleiteter Go-TypHinweise
"hallo"stringImmer eindeutig
true / falseboolImmer eindeutig
42intGanze Zahlen standardmäßig int
3.14float64Jede Dezimalzahl wird zu float64
{ ... }verschachteltes structWird zu einem eigenen benannten Typ
[ ... ][]TElementtyp wird aus Elementen abgeleitet
nullinterface{}Keine Typinformationen verfügbar

Die beiden Fälle, die Ihre Aufmerksamkeit verdienen, sind Zahlen und null. Alles andere bekommt der Konverter jedes Mal richtig hin.

Warum int vs. float64 die kniffligste Entscheidung ist#

JSON hat keinen Integer-Typ. Die Zahl 5 und die Zahl 5.0 sind für einen JSON-Parser beide nur "Zahl". Ein Generator muss raten: Wenn das Literal keinen Dezimalpunkt hat, wählt er int; wenn er einen Dezimalpunkt sieht, wählt er float64.

Diese Heuristik versagt auf eine häufige Weise. Stellen Sie sich ein API-Feld price vor, das in Ihrem Beispiel zufällig 100 ist, aber normalerweise 100.50. Der Konverter sieht eine ganze Zahl und schreibt int. Die nächste Antwort mit 100.50 kann dann nicht in ein int unmarshallet werden oder wird schlimmstenfalls abgeschnitten.

Überprüfen Sie Zahlenfelder immer anhand der API-Dokumentation, nicht nur anhand Ihres einen Beispiels. Wenn ein Feld jemals einen Bruchteil enthalten kann, ändern Sie das generierte int manuell in float64. Ein einzelnes sauberes Beispiel ist kein Schema.

Es gibt auch die Option json.Number. Wenn Präzision wichtig ist (große IDs, Geld, alles, was Sie sich nicht leisten können zu runden), decodieren Sie in json.Number oder einen String und parsen Sie bewusst. Generatoren standardmäßig auf float64 für Dezimalzahlen, was für die meisten Daten in Ordnung ist, aber für 64-Bit-Integer-IDs über 2^53 verlustbehaftet ist.

Wenn Sie einen leeren Interface-Typ erhalten#

Wenn ein JSON-Wert null ist, hat der Konverter nichts, woraus er ableiten könnte. Es gibt keinen Typ, nur die Abwesenheit eines solchen. Also fällt er zurück auf interface{} (in modernem Go als any geschrieben).

Derselbe Fallback tritt bei Arrays mit gemischten Typen auf. Ein JSON-Array wie [1, "zwei", true] hat keinen einzelnen Elementtyp, also erzeugt der Generator []interface{}. Das ist technisch korrekt, aber schrecklich zu handhaben, weil Sie die gesamte Typsicherheit zur Compile-Zeit verlieren und jedes Element typbehaupten müssen.

Wenn Sie interface{} in der generierten Ausgabe sehen, behandeln Sie es als Flagge, die sagt: "Ich konnte das nicht herausfinden, entscheiden Sie." Meistens ist der richtige Schritt, dem Konverter ein reichhaltigeres Beispiel zu geben, in dem dieses Feld befüllt ist, und dann neu zu generieren.

Feld-Tags, exportierte Namen und omitempty#

Den richtigen Typ zu finden ist die halbe Arbeit. Die andere Hälfte sind die json:-Struct-Tags und die Feldbenennung, wo handgeschriebene Structs am häufigsten scheitern.

Warum Felder exportiert werden müssen (Großschreibung)#

Das encoding/json-Paket von Go kann nur exportierte Struct-Felder lesen und schreiben, also Felder, deren Name mit einem Großbuchstaben beginnt. Ein nicht exportiertes (kleingeschriebenes) Feld ist für Unmarshal und Marshal unsichtbar. Es bleibt still auf seinem Nullwert, ohne Fehler.

Ein JSON-Key user_name kann also nicht auf ein Go-Feld namens user_name abgebildet werden. Der Konverter benennt es in das exportierte UserName um und fügt ein Tag hinzu, um die Lücke zu schließen:

type User struct {
    UserName string `json:"user_name"`
    Email    string `json:"email"`
}

Das Tag json:"user_name" teilt dem JSON-Paket mit: Dieses exportierte UserName-Feld entspricht dem JSON-Key user_name. Ohne dieses Tag würde Go nach einem Key namens UserName suchen (es führt einen case-insensitiven Match als Fallback durch, aber darauf zu vertrauen ist fragil). Die Konvertierung von snake_case oder camelCase zu PascalCase plus einem expliziten Tag ist genau das, was ein guter Generator automatisiert.

Was omitempty tatsächlich ändert#

Die Option omitempty erscheint in Tags wie json:"email,omitempty". Sie betrifft nur das Marshaling (Go-Struct zu JSON), niemals das Unmarshaling. Wenn Sie ein Struct kodieren, weist omitempty den Encoder an, ein Feld ganz zu überspringen, wenn sein Wert der Nullwert ist (leerer String, 0, false, nil, leeres Slice oder Map).

Dies ist für die API-Ausgabe wichtig. Vergleichen Sie dasselbe Struct mit und ohne:

TagFeldwertJSON-Ausgabe
json:"middle_name""" (leer)"middle_name": ""
json:"middle_name,omitempty""" (leer)(Feld weggelassen)
json:"age,omitempty"0(Feld weggelassen)

Die Falle bei omitempty ist, dass es nicht zwischen "absichtlich null" und "nicht gesetzt" unterscheiden kann. Wenn age legitimerweise 0 ist (ein Neugeborenes), entfernt omitempty es aus der Ausgabe. Wenn Sie "abwesend" von "null" unterscheiden müssen, verwenden Sie stattdessen ein Zeigerfeld (*int), wobei nil für abwesend und &zero für eine echte Null steht.

Die meisten Konverter fügen omitempty nicht standardmäßig hinzu, da es eine Serialisierungsentscheidung und keine Schema-Tatsache ist. Fügen Sie es bewusst bei Feldern hinzu, die in Ihrer Ausgabe wirklich optional sind, und greifen Sie zu Zeigerfeldern, wenn der Nullwert bedeutungsvoll ist.

Umgang mit verschachtelten und wiederholten Strukturen#

Echte API-Antworten sind selten flach. Sie verschachteln Objekte ineinander und enthalten Arrays von Objekten. Hier wird das manuelle Schreiben von Structs richtig mühsam und ein Konverter verdient seinen Lohn.

Wenn ein Konverter auf ein verschachteltes Objekt trifft, hat er zwei Strategien:

  • Inline (anonyme) Struktur: Der verschachtelte Typ wird direkt in das übergeordnete Objekt geschrieben. Kompakt, aber Sie können den inneren Typ nicht anderweitig referenzieren.
  • Benannte (extrahierte) Typen: Jedes verschachtelte Objekt wird zu einem eigenen benannten struct, das vom übergeordneten Objekt referenziert wird. Ausführlicher, aber wiederverwendbar und viel lesbarer.

Für alles, was über eine triviale Nutzlast hinausgeht, bevorzugen Sie benannte Typen. Bei folgendem JSON:

{
  "id": 7,
  "owner": { "name": "Ada", "verified": true },
  "tags": ["go", "json"]
}

Erzeugt ein Konverter mit benannten Typen:

type Repo struct {
    ID    int      `json:"id"`
    Owner Owner    `json:"owner"`
    Tags  []string `json:"tags"`
}

type Owner struct {
    Name     string `json:"name"`
    Verified bool   `json:"verified"`
}

Beachten Sie, dass tags zu []string wurde, weil jedes Element ein String war, und owner zu einem eigenen Owner-Typ. Bei einem Array von Objekten ("items": [ {...}, {...} ]) untersucht der Konverter das erste Element (oder führt eine Zusammenführung über alle Elemente durch, wenn er intelligent ist) und erzeugt []Item mit einem generierten Item-Struct.

Der Sonderfall der Array-Zusammenführung#

Hier ist eine Feinheit, die billigere Generatoren übersehen. Wenn ein Array Objekte enthält, bei denen einige Elemente ein Feld haben und andere nicht, liest ein naiver Konverter nur das erste Element und übersieht Felder, die später auftauchen. Ein robuster Generator führt Schlüssel über alle Elemente des Arrays zusammen, sodass das Struct jedes Feld erfasst und Felder, die manchmal fehlen, als Kandidaten für Zeiger oder omitempty markiert. Wenn Ihr generiertes Struct Felder auslässt, die tiefer in einer Liste existieren, ist das die Ursache.

Ein Go-Struct aus JSON generieren, Schritt für Schritt#

Sie können dies in Ihrem Browser in unter einer Minute erledigen, ohne Go-Toolchain oder go install. Molixas kostenloser JSON-Formatierer und Konverter validiert zuerst Ihr JSON und erzeugt dann ein Go-Struct (neben TypeScript, Zod und anderen Zielen), sodass Sie Syntaxprobleme erkennen, bevor sie zu Go-Kompilierungsfehlern werden.

Schritt 1: JSON einfügen und validieren#

Fügen Sie eine repräsentative Antwort in den Editor ein. Das wichtigste Wort dabei ist repräsentativ: Verwenden Sie ein Beispiel mit allen gefüllten Feldern und realistischen Werten, nicht ein abgespecktes. Leere oder null-lastige Beispiele erzeugen genau die interface{}-Felder. Der Formatierer markiert sofort nachgestellte Kommas, einfache Anführungszeichen und nicht in Anführungszeichen gesetzte Schlüssel, was weit weniger schmerzhaft ist als später einen Go-Unmarshal-Fehler zu jagen.

Schritt 2: Go-Struct-Ausgabe generieren#

Schalten Sie die Ausgabe auf das Go-Struct-Ziel um. Der Konverter durchläuft Ihr JSON, leitet jeden Typ ab, exportiert und benennt Felder in PascalCase um und schreibt passende json:-Tags. Verschachtelte Objekte werden zu benannten Typen und Arrays automatisch zu Slices. Kopieren Sie das Ergebnis direkt in Ihr Paket.

Schritt 3: Mehrdeutige Felder manuell korrigieren#

Dies ist der Schritt, den Generatoren nicht für Sie erledigen können, und das Überspringen ist der Grund, warum Leute Konverter für unzuverlässig halten. Durchsuchen Sie die Ausgabe nach drei Dingen:

  • int-Felder, die Dezimalzahlen enthalten können: Ändern Sie zu float64 (oder json.Number für Präzision).
  • interface{}-Felder: Diese stammen von null oder gemischten Arrays. Ersetzen Sie sie durch einen konkreten Typ oder füttern Sie ein reichhaltigeres Beispiel und generieren Sie neu.
  • Große Integer-IDs: Wenn eine ID 2^53 überschreitet, verliert ein float64 an Präzision. Verwenden Sie int64, string oder json.Number, je nach API.

Schritt 4: omitempty und Zeiger hinzufügen, wo sie hingehören#

Entscheiden Sie pro Feld, ob es bei der Ausgabe wirklich optional ist. Fügen Sie ,omitempty zu Feldern hinzu, die verschwinden sollen, wenn sie leer sind. Bei Feldern, bei denen ein Nullwert sinnvoll ist (eine echte 0, ein echtes false), wechseln Sie zu einem Zeigertyp, sodass nil sauber „nicht bereitgestellt“ signalisiert. Schreiben Sie dann einen kleinen Unmarshal-Test gegen Ihr echtes Beispiel, um zu bestätigen, dass nichts stillschweigend verworfen wird.

Vertrauen in die Ausgabe: Prüfen, bevor Sie ausliefern#

Eine generierte Struktur ist ein solider erster Entwurf, keine Garantie. Der ehrliche Workflow ist: generieren, dann nachweisen, dass sie Ihre echten Daten korrekt abbildet. Entpacken Sie eine echte Antwort in die Struktur, packen Sie sie zurück und vergleichen Sie sie mit dem Original. Fehlende oder umsortierte Felder fallen sofort auf.

Wenn Sie auch in TypeScript an derselben API arbeiten, kann dasselbe JSON-Beispiel beide Seiten antreiben. Unser Leitfaden zum Konvertieren von JSON in ein TypeScript-Interface behandelt die parallelen Typinferenzregeln im Frontend. Wenn Sie zuerst das rohe Payload debuggen, erklärt wie man JSON in JavaScript formatiert die hübsche Ausgabe und die JSON.stringify-Optionen, die eine unübersichtliche Antwort lesbar machen, bevor Sie sie konvertieren.

Der Grund, warum ein Konverter besser ist als manuelles Tippen, ist nicht nur die Geschwindigkeit. Er wendet die Exportregel, das Tag-Mapping und die Verschachtelung jedes Mal konsistent an, sodass Ihnen nur die kleinen Ermessensentscheidungen (int vs. float, optional vs. erforderlich, Genauigkeit) bleiben, die kein Tool aus einem einzelnen Beispiel ableiten kann. Diese Arbeitsteilung ist der ganze Sinn.

Fazit: Von rohem JSON zu einer zuverlässigen Go-Struktur#

Die Konvertierung von JSON in eine Go-Struktur ist für die meisten Felder mechanisch und für einige wenige eine Frage der Beurteilung. Ein Generator erledigt die mechanischen 90%: Exportieren von Feldern, Schreiben von json:-Tags, Benennen verschachtelter Typen und Umwandeln von Arrays in Slices. Sie kümmern sich um die 10%, die er nicht ableiten kann, hauptsächlich numerische Genauigkeit, aus null abgeleitete interface{}-Felder und ob omitempty oder ein Zeiger zu jedem optionalen Feld gehört.

Wenn Sie diese Regeln richtig anwenden, wird der Hin- und Rückweg von JSON zur Go-Struktur im besten Sinne langweilig. Fügen Sie eine repräsentative Stichprobe in den JSON-Formatter und Go-Struktur-Konverter ein, generieren Sie den Typ, korrigieren Sie die wenigen mehrdeutigen Felder und bestätigen Sie, dass der Hin- und Rückweg mit Ihren echten Daten funktioniert. Das ist der Unterschied zwischen einer Struktur, die kompiliert, und einer, der Sie in der Produktion tatsächlich vertrauen können.

Häufig gestellte Fragen#

Wie konvertiere ich JSON in eine Go-Struktur? Fügen Sie eine repräsentative JSON-Probe in einen Konverter ein, der für jeden Wert einen Go-Typ ableitet, Schlüssel in PascalCase exportiert und umbenennt und passende json:-Tags hinzufügt. Überprüfen Sie dann manuell numerische Felder und alle interface{}-Typen, die das Tool nicht ableiten konnte. Sie können das Ganze kostenlos im Browser mit Molixas JSON-Formatierer und -Konverter erledigen, ohne Go-Werkzeugkette.

Warum hat meine generierte Struktur interface{}-Felder? Ein interface{}-Feld (oder any) bedeutet, dass der Konverter keinen Typ ableiten konnte. Dies tritt auf, wenn der JSON-Wert null war oder wenn ein Array gemischte Typen enthielt. Die Lösung ist, eine Probe bereitzustellen, in der dieses Feld mit einem echten Wert gefüllt ist, und dann neu zu generieren, oder das interface{} durch den konkreten Typ zu ersetzen, von dem Sie wissen, dass er es sein sollte.

Müssen Go-Strukturfelder großgeschrieben werden? Ja, wenn encoding/json sie lesen oder schreiben soll. Das JSON-Paket von Go sieht nur exportierte Felder, also solche, die mit einem Großbuchstaben beginnen. Ein kleingeschriebenes Feld wird bei Marshal und Unmarshal ohne Fehler ignoriert, sodass es stillschweigend auf seinem Nullwert bleibt. Konverter exportieren jedes Feld und verwenden das json:-Tag, um auf den ursprünglichen Schlüsselnamen zurückzubilden.

Was bewirkt omitempty in einem JSON-Tag? Die Option omitempty betrifft nur das Marshalling (Codieren einer Struktur in JSON). Sie teilt dem Encoder mit, ein Feld zu überspringen, wenn sein Wert der Nullwert ist: leere Zeichenkette, 0, false, nil oder eine leere Slice oder Map. Sie hat keine Auswirkung auf das Unmarshalling. Seien Sie vorsichtig, da sie nicht zwischen einer absichtlichen Null und einem nicht gesetzten Feld unterscheiden kann. Verwenden Sie daher einen Zeigertyp, wenn der Nullwert bedeutsam ist.

Sollte ich int oder float64 für JSON-Zahlen in Go verwenden? Verwenden Sie float64 für jedes Feld, das eine Dezimalzahl enthalten kann, und int nur für Werte, die immer ganzzahlig sind. Da JSON keinen Integer-Typ hat, raten Konverter aus Ihrer Probe; ein Feld, das in der Probe 100 ist, aber manchmal 100.50, erhält den falschen Typ. Für große IDs oder Geldbeträge, bei denen Genauigkeit wichtig ist, bevorzugen Sie int64, string oder json.Number, um Float-Rundungen zu vermeiden.

Wie behandle ich verschachtelte JSON-Objekte in einer Go-Struktur? Konvertieren Sie jedes verschachtelte Objekt in einen eigenen benannten Strukturtyp, der von der übergeordneten Struktur referenziert wird, anstatt alles inline zu setzen. Dies hält den Code lesbar und ermöglicht die Wiederverwendung des inneren Typs. Ein guter Konverter macht dies automatisch und behandelt auch Arrays von Objekten, indem er einen Slice einer benannten Struktur generiert, idealerweise unter Zusammenführung der Schlüssel über alle Array-Elemente hinweg, damit kein Feld fehlt.

jsongolangcode-generationdeveloper-tools

More from Molixa

Try Molixa Tools

50+ free AI tools for content creation, SEO, coding, and more. No signup, no watermark.

Explore all tools
JSON zu Go-Struct Konverter Leitfaden | Molixa