Workflow de nomenclatura da API

API Request & Response Case Converter

Mantenha camelCase dentro da aplicação e traduza JSON snake_case na fronteira de request/response. Teste os dois sentidos e copie um padrão com Fetch ou Axios.

Resposta: snake_case → camelCase · Requisição: camelCase → snake_case

Direção da fronteira da API

API snake_case → aplicação camelCase
JSON camelCase da aplicação
{
  "userProfile": {
    "firstName": "Ada",
    "createdAt": "2026-09-12"
  }
}
Chaves renomeadas: 3A conversão do payload roda localmente no navegador.

Gerar código da fronteira da API

Escolha um padrão de cliente HTTP JSON. O exemplo converte objetos de saída para snake_case e respostas JSON recebidas para 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
}

Esta fronteira é intencionalmente para payloads JSON. Mantenha FormData, Blob, streams, arquivos e outros corpos não JSON fora do mapper.

Centralize a conversão na fronteira da API

Componentes, hooks, stores e código de domínio mantêm uma convenção interna enquanto o contrato JSON externo pode usar outra.

1. Normalize respostas recebidas

Depois de analisar o JSON do servidor, converta recursivamente chaves snake_case para camelCase antes do uso na aplicação.

2. Normalize requisições enviadas

Antes de serializar JSON, converta chaves camelCase da aplicação para o snake_case esperado pela API.

3. Deixe corpos não JSON fora do mapper

Não processe FormData, Blob, streams, arquivos ou instâncias arbitrárias de classe como objetos JSON.

Precisa de stop paths, exclusões regex, diff ou arquivos JSON locais?

Use o JSON Key Case Converter para regras avançadas de objeto e leve a mesma política para o código da aplicação.

Abrir JSON Key Case Converter

Guias de implementação de API

Escolha o guia adequado ao cliente HTTP, query function, serializer ou camada de modelos.