API-Naming-Workflow

API Request & Response Case Converter

Behalte camelCase innerhalb deiner Anwendung und übersetze snake_case-JSON an der Request-/Response-Grenze. Teste beide Richtungen und kopiere ein Fetch- oder Axios-Muster.

Response: snake_case → camelCase · Request: camelCase → snake_case

API-Grenzrichtung

snake_case API → camelCase App
camelCase-JSON der App
{
  "userProfile": {
    "firstName": "Ada",
    "createdAt": "2026-09-12"
  }
}
Umbenannte Schlüssel: 3Die Payload-Konvertierung läuft lokal im Browser.

API-Grenzcode erzeugen

Wähle ein JSON-HTTP-Client-Muster. Das Beispiel konvertiert ausgehende App-Objekte in snake_case und eingehende JSON-Antworten in camelCase.

type JsonRecord = Record<string, unknown>

function isJsonObject(value: unknown): value is JsonRecord {
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
    return false
  }
  return Object.getPrototypeOf(value) === Object.prototype
}

function splitPrefix(key: string) {
  const prefix = key.match(/^[_$]+/u)?.[0] ?? ""
  return { prefix, value: key.slice(prefix.length) }
}

function splitWords(value: string) {
  return value
    .replace(/([A-Z]+)([A-Z][a-z])/gu, "$1 $2")
    .replace(/([a-z0-9])([A-Z])/gu, "$1 $2")
    .split(/[^A-Za-z0-9]+/u)
    .filter(Boolean)
}

function toCamelKey(key: string) {
  const { prefix, value } = splitPrefix(key)
  const words = splitWords(value).map((word) => word.toLowerCase())
  const [firstWord, ...restWords] = words
  if (!firstWord) return key
  return prefix + firstWord + restWords
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
    .join("")
}

function toSnakeKey(key: string) {
  const { prefix, value } = splitPrefix(key)
  const words = splitWords(value).map((word) => word.toLowerCase())
  return words.length ? prefix + words.join("_") : key
}

function mapJsonKeys(
  value: unknown,
  convertKey: (key: string) => string,
): unknown {
  if (Array.isArray(value)) {
    return value.map((item) => mapJsonKeys(item, convertKey))
  }

  if (!isJsonObject(value)) {
    return value
  }

  const output: JsonRecord = {}
  for (const [key, child] of Object.entries(value)) {
    const nextKey = convertKey(key)
    if (Object.hasOwn(output, nextKey)) {
      throw new Error(`Key collision after case conversion: ${nextKey}`)
    }
    output[nextKey] = mapJsonKeys(child, convertKey)
  }
  return output
}

export function keysToCamel(value: unknown) {
  return mapJsonKeys(value, toCamelKey)
}

export function keysToSnake(value: unknown) {
  return mapJsonKeys(value, toSnakeKey)
}

export async function apiJson<T>(
  url: string,
  options: { method?: string; body?: unknown } = {},
): Promise<T> {
  const response = await fetch(url, {
    method: options.method ?? (options.body === undefined ? "GET" : "POST"),
    headers: { "content-type": "application/json" },
    body:
      options.body === undefined
        ? undefined
        : JSON.stringify(keysToSnake(options.body)),
  })

  if (!response.ok) {
    throw new Error(`API request failed: ${response.status}`)
  }

  const wireData: unknown = await response.json()
  return keysToCamel(wireData) as T
}

Die erzeugte Grenze ist für JSON-Payloads gedacht. FormData, Blob, Streams, Dateien und andere Nicht-JSON-Bodys bleiben außerhalb des Mappers.

Namenskonvertierung an der API-Grenze bündeln

Komponenten, Hooks, Stores und Domain-Code behalten eine interne Konvention, während der externe JSON-Vertrag eine andere nutzen kann.

1. Eingehende Antworten normalisieren

Nach dem Parsen des Server-JSON werden snake_case-Schlüssel rekursiv in camelCase umgewandelt.

2. Ausgehende Requests normalisieren

Vor der JSON-Serialisierung werden camelCase-Schlüssel der App in das von der API erwartete snake_case umgewandelt.

3. Nicht-JSON-Bodys außerhalb lassen

FormData, Blob, Streams, Dateien oder beliebige Klasseninstanzen nicht durch einen JSON-Key-Mapper schicken.

Stop Paths, Regex-Ausschlüsse, Diff oder lokale JSON-Dateien nötig?

Nutze den JSON Key Case Converter für erweiterte Objektregeln und übertrage dieselbe Grenzlogik anschließend in den Anwendungscode.

JSON Key Case Converter öffnen

API-Workflow-Implementierungen

Wähle den passenden Guide für HTTP-Client, Query-Funktion, Serializer oder Model-Alias-Schicht.