← Zurück zum Blog

JSON in TypeScript konvertieren: Type-sichere Entwicklung

Lernen Sie, JSON in TypeScript-Typen zu konvertieren. Interfaces generieren, Type Guards, Validierung und Best Practices für type-sichere Apps.

Big JSON Team12 Min. Lesezeitprogramming
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

12 Min. Lesezeit

# JSON in TypeScript konvertieren

Ein umfassender Leitfaden für type-sichere JSON-Verarbeitung in TypeScript.

Warum TypeScript für JSON?

TypeScript bietet Type-Sicherheit bei der Arbeit mit JSON:

  • Compile-Zeit-Checks - Fehler früh erkennen
  • Auto-Vervollständigung - Bessere IDE-Unterstützung
  • Dokumentation - Selbstdokumentierender Code
  • Refactoring - Sicherer Code umstrukturieren

Interfaces definieren

Einfaches Interface

JSON:
{

"id": 1,

"name": "Max Mustermann",

"email": "max@example.de",

"aktiv": true

}

TypeScript Interface:
interface Benutzer {

id: number;

name: string;

email: string;

aktiv: boolean;

}

// Verwendung

const benutzer: Benutzer = {

id: 1,

name: "Max Mustermann",

email: "max@example.de",

aktiv: true

};

Verschachtelte Interfaces

JSON:
{

"name": "Max",

"adresse": {

"straße": "Hauptstraße 1",

"stadt": "Berlin",

"plz": "10115"

}

}

TypeScript:
interface Adresse {

straße: string;

stadt: string;

plz: string;

}

interface Person {

name: string;

adresse: Adresse;

}

Arrays

interface Produkt {

id: number;

name: string;

preis: number;

}

interface Shop {

produkte: Produkt[];

}

// Oder

interface Shop {

produkte: Array<Produkt>;

}

Automatische Type-Generierung

Online-Tools

quicktype.io:
  • JSON einfügen
  • TypeScript auswählen
  • Interfaces kopieren
  • json2ts.com:
    • Schnell und einfach
    • Gute Interface-Generierung

    VS Code Extensions

    Paste JSON as Code:
  • JSON kopieren
  • Cmd/Ctrl + Shift + P
  • "Paste JSON as Code"
  • Mit Bibliotheken

    npm install -g quicktype
    quicktype daten.json -o types.ts

    JSON-Parsing mit Types

    Basis-Parsing

    interface Benutzer {
    

    id: number;

    name: string;

    email: string;

    }

    const jsonString = '{"id":1,"name":"Max","email":"max@example.de"}';

    // ⚠️ Unsicher - kein Runtime-Check

    const benutzer = JSON.parse(jsonString) as Benutzer;

    // ⚠️ Type Assertion - keine Garantie

    const benutzer2: Benutzer = JSON.parse(jsonString);

    Mit Type Guards

    interface Benutzer {
    

    id: number;

    name: string;

    email: string;

    }

    function istBenutzer(obj: any): obj is Benutzer {

    return (

    typeof obj === 'object' &&

    obj !== null &&

    typeof obj.id === 'number' &&

    typeof obj.name === 'string' &&

    typeof obj.email === 'string'

    );

    }

    const jsonString = '{"id":1,"name":"Max","email":"max@example.de"}';

    const parsed = JSON.parse(jsonString);

    if (istBenutzer(parsed)) {

    // TypeScript weiß, dass parsed ein Benutzer ist

    console.log(parsed.email.toLowerCase());

    } else {

    console.error('Ungültige Benutzerdaten');

    }

    Runtime-Validierung

    Mit zod

    import { z } from 'zod';
    
    

    const BenutzerSchema = z.object({

    id: z.number(),

    name: z.string(),

    email: z.string().email(),

    alter: z.number().min(0).max(150).optional()

    });

    type Benutzer = z.infer<typeof BenutzerSchema>;

    // Validierung

    const jsonString = '{"id":1,"name":"Max","email":"max@example.de"}';

    const parsed = JSON.parse(jsonString);

    try {

    const benutzer: Benutzer = BenutzerSchema.parse(parsed);

    console.log(benutzer.email);

    } catch (error) {

    console.error('Validierungsfehler:', error);

    }

    Mit io-ts

    import * as t from 'io-ts';
    

    import { isRight } from 'fp-ts/Either';

    const BenutzerCodec = t.type({

    id: t.number,

    name: t.string,

    email: t.string,

    aktiv: t.boolean

    });

    type Benutzer = t.TypeOf<typeof BenutzerCodec>;

    const result = BenutzerCodec.decode(JSON.parse(jsonString));

    if (isRight(result)) {

    const benutzer: Benutzer = result.right;

    console.log(benutzer.name);

    } else {

    console.error('Ungültige Daten');

    }

    Optionale Felder

    interface Benutzer {
    

    id: number;

    name: string;

    email?: string; // Optional

    telefon?: string | null; // Optional oder null

    }

    const benutzer1: Benutzer = {

    id: 1,

    name: "Max"

    // email und telefon sind optional

    };

    const benutzer2: Benutzer = {

    id: 2,

    name: "Anna",

    email: "anna@example.de",

    telefon: null

    };

    Union Types

    type Status = 'aktiv' | 'inaktiv' | 'gesperrt';
    
    

    interface Benutzer {

    id: number;

    name: string;

    status: Status;

    }

    // Nur diese Werte sind erlaubt

    const benutzer: Benutzer = {

    id: 1,

    name: "Max",

    status: "aktiv" // ✅

    // status: "unbekannt" // ❌ Fehler!

    };

    Generics

    interface APIAntwort<T> {
    

    success: boolean;

    data: T;

    error?: string;

    }

    interface Benutzer {

    id: number;

    name: string;

    }

    // Verwendung

    const antwort: APIAntwort<Benutzer> = {

    success: true,

    data: {

    id: 1,

    name: "Max"

    }

    };

    const antwort2: APIAntwort<Benutzer[]> = {

    success: true,

    data: [

    { id: 1, name: "Max" },

    { id: 2, name: "Anna" }

    ]

    };

    JSON-Dateien importieren

    tsconfig.json konfigurieren

    {
    

    "compilerOptions": {

    "resolveJsonModule": true,

    "esModuleInterop": true

    }

    }

    Import

    // daten.json
    

    {

    "name": "Konfiguration",

    "version": "1.0.0"

    }

    // app.ts

    import daten from './daten.json';

    console.log(daten.name); // ✅ Type-sicher!

    console.log(daten.version); // ✅ Auto-Vervollständigung

    Mit Type

    interface Config {
    

    name: string;

    version: string;

    }

    import daten from './daten.json';

    const config: Config = daten;

    Fetch mit TypeScript

    interface Benutzer {
    

    id: number;

    name: string;

    email: string;

    }

    async function holeBenutzer(id: number): Promise<Benutzer> {

    const response = await fetch(/api/benutzer/\\${id});

    if (!response.ok) {

    throw new Error(HTTP \\${response.status});

    }

    const daten = await response.json();

    // Mit Validierung (zod)

    return BenutzerSchema.parse(daten);

    }

    // Verwendung

    const benutzer = await holeBenutzer(1);

    console.log(benutzer.email); // ✅ Type-sicher

    Utility Types

    Partial

    interface Benutzer {
    

    id: number;

    name: string;

    email: string;

    }

    // Alle Felder optional

    type BenutzerUpdate = Partial<Benutzer>;

    const update: BenutzerUpdate = {

    email: "neue@email.de"

    // Nur email, rest ist optional

    };

    Pick

    type BenutzerPreview = Pick<Benutzer, 'id' | 'name'>;
    
    

    const preview: BenutzerPreview = {

    id: 1,

    name: "Max"

    // email fehlt - ist nicht Teil von Pick

    };

    Omit

    type BenutzerOhneId = Omit<Benutzer, 'id'>;
    
    

    const neuerBenutzer: BenutzerOhneId = {

    name: "Max",

    email: "max@example.de"

    // id fehlt - wurde mit Omit entfernt

    };

    Best Practices

    1. Immer validieren

    // ❌ Schlecht - nur Type Assertion
    

    const benutzer = JSON.parse(json) as Benutzer;

    // ✅ Gut - mit Validierung

    const benutzer = BenutzerSchema.parse(JSON.parse(json));

    2. Strikte null Checks

    // tsconfig.json
    

    {

    "compilerOptions": {

    "strictNullChecks": true

    }

    }

    interface Benutzer {
    

    name: string;

    email: string | null; // Explizit null erlaubt

    }

    3. Readonly für Konstanten

    interface Config {
    

    readonly apiUrl: string;

    readonly timeout: number;

    }

    const config: Config = {

    apiUrl: "https://api.example.com",

    timeout: 5000

    };

    // config.apiUrl = "..."; // ❌ Fehler - readonly

    4. Type Guards verwenden

    function istBenutzerArray(arr: any): arr is Benutzer[] {
    

    return Array.isArray(arr) && arr.every(istBenutzer);

    }

    Komplexe Beispiele

    Verschachtelte API-Antwort

    interface Pagination {
    

    seite: number;

    proSeite: number;

    gesamt: number;

    }

    interface APIListe<T> {

    erfolg: boolean;

    daten: T[];

    pagination: Pagination;

    }

    interface Produkt {

    id: number;

    name: string;

    preis: number;

    }

    type ProduktListe = APIListe<Produkt>;

    const antwort: ProduktListe = {

    erfolg: true,

    daten: [

    { id: 1, name: "Laptop", preis: 899 },

    { id: 2, name: "Maus", preis: 29 }

    ],

    pagination: {

    seite: 1,

    proSeite: 10,

    gesamt: 2

    }

    };

    Zusammenfassung

    Wichtigste Tools

  • zod - Runtime-Validierung
  • quicktype - Type-Generierung
  • io-ts - Funktionale Validierung
  • Checkliste

    ✅ Interfaces für alle JSON-Strukturen

    ✅ Runtime-Validierung verwenden

    ✅ Type Guards implementieren

    ✅ Strikte Compiler-Optionen

    ✅ Generierte Types nutzen

    Weiterführende Ressourcen

    Share:

    Verwandte Artikel

    Read in English