JSON zu TypeScript
JSON-Daten automatisch in TypeScript Interfaces oder Typ-Definitionen konvertieren
// Nach JSON-Eingabe werden TypeScript-Typ-Definitionen automatisch generiertWas ist JSON zu TypeScript?
JSON to TypeScript analysiert eine JSON-Struktur und erzeugt daraus TypeScript-Typen oder Interfaces. Das ist hilfreich, wenn API-Antworten, Konfigurationsdateien, Beispieldaten oder Mock-Daten schnell in typisierte Frontend- oder Node.js-Projekte übernommen werden sollen. Das Werkzeug erkennt Objekte, Arrays, verschachtelte Felder, optionale Eigenschaften und einfache Werttypen, sodass aus Rohdaten ein Ausgangspunkt für stabile Typdefinitionen entsteht. Trotzdem bleibt eine fachliche Prüfung nötig: Beispiel-JSON zeigt oft nur einen Ausschnitt, leere Arrays verraten keine Elementstruktur, und echte APIs können zusätzliche Felder oder null-Werte liefern. Die generierten Typen sollten daher als solide Vorlage und nicht als endgültiger Vertrag verstanden werden.
Anleitung
So geht's
- JSON-Daten in das linke Eingabefeld einfügen oder auf die Schaltfläche 'Beispiel' klicken, um Beispieldaten zu laden
- Optionen konfigurieren: Root-Typ-Namen festlegen, Interface- oder Type-Stil auswählen, festlegen, ob 'export' hinzugefügt werden soll usw.
- Die entsprechenden TypeScript-Typdefinitionen werden automatisch auf der rechten Seite erzeugt
- Auf die Schaltfläche 'Kopieren' klicken, um die generierten Typdefinitionen in die Zwischenablage zu kopieren
- Die Typdefinitionen in Ihr TypeScript-Projekt einfügen und dort verwenden
Hinweise zur Typgenerierung
- Verwenden Sie repräsentative JSON-Beispiele. Ein einzelnes Beispiel kann nicht jedes optionale Feld, jeden Nullable-Wert oder jeden Union-Typ in einer echten API aufdecken.
- Überprüfen Sie die generierten Namen vor der Übernahme, insbesondere bei verschachtelten Objekten, wo automatische Interface-Namen zu allgemein sein können.
Anwendungsfälle
Technisches Prinzip
JSON zu TypeScript ist im Wesentlichen ein 'Strukturinferenz'-Prozess. Das Werkzeug durchläuft rekursiv jeden Knoten des JSON-Baums und bildet den Laufzeittyp jedes Werts auf einen TypeScript-Typ ab: string -> string, number -> number, boolean -> boolean, null -> null, object -> Sub-Interface, array -> Array des Elementtyps. Die Ausgabe ist eine Reihe von TypeScript-`interface`-Deklarationen (oder `type`-Aliase, wenn der 'type'-Ausgabemodus gewählt ist) sowie alle verschachtelten Interfaces, die aus objektwertigen Feldern extrahiert werden. Der schwierige Teil der Inferenz ist die Union- vs. Einzeltyp-Entscheidung für Arrays. Wenn jedes Element eines Arrays denselben Typ hat, ist die Ausgabe `T[]` (homogenes Array). Wenn Elemente verschiedene Typen haben, ist die Ausgabe die Vereinigung dieser Typen: `[1, 'a', true]` wird zu `(number | string | boolean)[]`. Wenn die Eingabe ein Objekt ist, das Literal- und Strukturwerte mischt (z. B. `{ id: 1, name: 'Alice', tags: ['admin', 'editor'] }`), erhält jedes Feld seinen eigenen Typ; für Objekte mit gemischten primitiven Werten gibt die Seite ein einzelnes Interface aus, keine Union, da dies das ist, was TypeScript-Code erwartet (und der Natur von JSON-Objekten als Record-Typ entspricht). Mehrere Beispielelemente (der typische Anwendungsfall: ein JSON-Array einfügen) werden durch Schnittmengen ihrer Strukturen zusammengeführt. Felder, die in jedem Beispiel vorhanden sind, werden erforderlich; Felder, die in einem Beispiel fehlen, werden optional (`fieldName?: T`). Dies ist das richtige Verhalten für API-Antworten: Eine 200-OK-Antwort hat eine Struktur, eine 404-Antwort eine andere, und die Vereinigung beider ist der richtige TS-Typ. Bei einem einzelnen Beispiel ist jedes Feld erforderlich. Die Namensnormalisierung ist der Punkt, an dem die meisten 'JSON-zu-TS'-Werkzeuge scheitern. JSON-Keys sind meist snake_case (`user_id`, `created_at`) oder camelCase (`userId`, `createdAt`); TypeScript-Konvention ist PascalCase für Interface-Namen (`UserProfile`, `AuditEntry`) und camelCase für Eigenschaftsnamen. Die Seite konvertiert JSON-Keys zu camelCase (oder belässt sie, wenn sie bereits camelCase oder ein einzelnes Wort sind) und PascalCase für Interface-Namen. Innere Objekte werden in benannte Interfaces extrahiert: `{ user: { name, age } }` wird zu `interface User { name: string; age: number; }` und das Elternelement wird zu `interface Root { user: User; }`. Rekursive Strukturen (ein Baumknoten mit einem `children: TreeNode[]`-Feld) erhalten eine Selbstreferenz über eine vorangestellte `type`-Deklaration statt `interface`, sodass der Zyklus wohldefiniert ist. Der 'Root'-Schalter ist der Unterschied zwischen einem Array-Root und einem Objekt-Root. Ein JSON-Array wird zu `type Root = Item[]` oder `interface Root { items: Item[]; ... }` je nach Wrap-Array-Schalter. Ein JSON-Objekt wird zu einem flachen Interface auf der obersten Ebene. Datum-Strings (RFC 3339 / ISO 8601) können als `Date` statt `string` markiert werden; UUIDs, E-Mails und URLs können als Branded Types (`type UUID = string & { readonly __brand: 'UUID' };`) markiert werden, wenn der Strict-Mode-Schalter aktiviert ist. Die JSDoc-Generierung ist heuristisch: Ein Feld namens `email` (und dessen Wert einem grundlegenden E-Mail-Regex entspricht) erhält einen Kommentar wie `/** user email */` über der Deklaration. Dasselbe gilt für `id`, `name`, `url`, `created_at`/`createdAt`, `updated_at`/`updatedAt`, `description`, `title`. Die Kommentare sind nach bestem Bemühen und geben nicht vor, von Menschen geschrieben zu sein; sie sind ein Ausgangspunkt, den Menschen bearbeiten werden. Die Seite gibt auch `export`-Modifikatoren aus, damit die Ausgabe direkt in jede TS-Datei eingefügt werden kann, sowie einen `// generated by json-to-typescript, do not edit by hand`-Header, um manuelle Bearbeitungen abzuschrecken, die beim nächsten Regenerieren des Schemas überschrieben würden.
- Atomare Typzuordnung: JSONs string/number/boolean/null bilden sich eins zu eins auf TypeScripts string/number/boolean/null ab. Große Ganzzahlen (>2^53) benötigen BigInt; die Seite markiert sie als `bigint`, wenn der Wert Number.MAX_SAFE_INTEGER überschreitet.
- Array-Typinferenz: Alle Elemente durchlaufen und die Vereinigung ihrer Typen bilden; identische Typen kollabieren zu `T[]`, verschiedene Typen bilden `(A | B | C)[]`. Leere Arrays werden zu `unknown[]`, da der Elementtyp unbekannt ist.
- Verschachtelte Objekt-Extraktion: Innere Objekte werden automatisch in benannte Interfaces angehoben. Rekursive Strukturen verwenden `type Name = ...` (nicht `interface`), sodass die Vorwärtsreferenz in TypeScripts Typprüfer wohldefiniert ist.
- Optionale Feld-Erkennung: Wenn mehrere Beispielelemente zusammengeführt werden, werden Felder, die in jedem Beispiel vorhanden sind, erforderlich; Felder, die in einem Beispiel fehlen, werden optional (`fieldName?: T`). Einzelbeispiel-Eingabe markiert jedes Feld als erforderlich.
- Namenskonvention: JSON-Keys werden zu camelCase für Eigenschaftsnamen konvertiert (user_id -> userId, created_at -> createdAt) und PascalCase für Interface-Namen (UserProfile, AuditEntry). Einzelwort-Keys bleiben erhalten; Zahlen in Keys bleiben erhalten; führende Ziffern werden mit Unterstrich vorangestellt, um gültige TS-Bezeichner zu bleiben.
- Root-Schalter: Array-Root -> `export type Root = Item[]` (oder eingehüllt in `{ items: Item[]; }` wenn Wrap-Array aktiviert); Objekt-Root -> ein einzelnes `export interface Root { ... }`. Rekursive Strukturen erhalten zuerst eine Stub-Vorwärtsdeklaration.
- JSDoc-Kommentare: Heuristische Kommentargenerierung für bekannte Feldnamen (email, id, name, url, createdAt, updatedAt, description, title). Die Ausgabe enthält `export`-Modifikatoren und einen `// generated, do not edit by hand`-Header, um manuelle Bearbeitungen abzuschrecken.
- Strict-Mode: Opt-in für Branded Types (UUID, Email, URL, Date), Readonly-Modifikatoren, exactOptionalPropertyTypes und noUncheckedIndexedAccess. Die Seite gibt `type UUID = string & { readonly __brand: 'UUID' };` aus, wenn der Strict-Mode aktiviert ist, sodass nachgelagerter Code einen rohen String von einem typisierten Wert unterscheiden kann.
Beispiele
Einfaches Objekt zu interface
{"id": 1, "name": "Alice", "active": true}
->
interface User {
id: number;
name: string;
active: boolean;
}Verschachteltes Objekt erzeugt Sub-Interfaces
{"user": {"name": "Alice", "address": {"city": "NYC"}}}
->
interface Root {
user: User;
}
interface User {
name: string;
address: Address;
}
interface Address {
city: string;
}Array zu readonly Tuple
[{"id": 1}, {"id": 2}]
->
interface Item {
id: number;
}
type Root = readonly Item[];FAQ
Welche TypeScript-Konstrukte werden erzeugt?
Standardmäßig Interfaces – eines pro Objektform. Optionale Felder bekommen das ?-Zeichen. Arrays werden zu T[]. Gemischte Arrays werden zur Vereinigung. Strings mit erkennbarem Format (z. B. ISO-Daten) bleiben string, sofern du nicht Branded Types aktivierst. Manche Seiten bieten alternativ type-Aliase statt interface.
Wie werden verschachtelte Objekte behandelt?
Jede unterschiedliche verschachtelte Form bekommt ein eigenes Interface, benannt nach dem Eigenschaftspfad (User, UserAddress, UserPreferences). Teilen sich zwei Eigenschaften dieselbe Form, dedupliziert der Generator je nach Einstellung – prüfe die Ausgabe und führe gegebenenfalls per Hand zusammen.
Sind Eigenschaften required oder optional?
Standardmäßig sind Eigenschaften, die im Beispiel vorkommen, required. Eigenschaften, die nur in manchen Array-Elementen auftauchen, werden mit ? als optional markiert. Schalte „alle optional“ um, wenn dein Beispiel nur eine Form unter vielen möglichen ist.
Wie werden null und undefined behandelt?
null in JSON wird zu null in TypeScript (nicht zu undefined). Eine Eigenschaft, die mal ein String und mal null ist, wird zu string | null. JSON kennt kein undefined, deshalb gibt der Generator nie direkt undefined aus.
Was ist mit Union-Types und Discriminated Unions?
Enthält ein Array gemischte Objektformen, gibt der Generator eine Vereinigung von Interfaces aus. Er erkennt kein Discriminator-Feld automatisch; schreibe die Ausgabe per Hand in eine Discriminated Union um (z. B. mit einem kind-Tag), wenn du erschöpfendes Type Narrowing willst.
Wird das JSON hochgeladen?
Nein. Die Konvertierung läuft im Browser über einen JS-basierten JSON-Parser und String-Templates. Eingefügtes JSON verlässt dein Gerät nicht.
Stimmt das Ergebnis mit den tatsächlichen Backend-Antworten überein?
Nur so gut wie das Beispiel. Validiere Laufzeitdaten immer gegen ein Schema (Zod, io-ts, Yup) – TypeScript-Typen werden zur Laufzeit gelöscht und können nicht erkennen, wenn das Backend vom Beispiel abweicht.