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
{
"userProfile": {
"firstName": "Ada",
"createdAt": "2026-09-12"
}
}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 ConverterGuias de implementação de API
Escolha o guia adequado ao cliente HTTP, query function, serializer ou camada de modelos.
Fetch API
Envolva requisições e respostas JSON sem tocar corpos não JSON.
Axios
Use uma instância Axios dedicada com interceptors de request/response.
TanStack Query
Faça o mapeamento em funções query/mutation compartilhadas, não nos componentes.
Jackson
Aplique estratégias de nomenclatura nas fronteiras de serialização Java.
Pydantic
Use aliases de modelos para separar campos Python do JSON externo.
Dicionários Python
Converta chaves de dict/list recursivamente quando não houver camada de modelos.