Erro FiveM json.decode: correções para nil, string vazia e JSON inválido
json.decode falha ou retorna nil em seu script FiveM? Por que decodificar nil, JSON vazio ou editado manualmente quebra, o que json.encode faz com chaves mistas, e como usar pcall com segurança.
O erro aparece uma linha após a decodificação:
SCRIPT ERROR: @my_script/server/main.lua:31: attempt to index a nil value (local 'data')local data = json.decode(row.metadata)
print(data.level) -- data is niljson.decode não lhe deu nada utilizável, então a próxima linha indexou nil. A decodificação raramente é a culpa real. A entrada era nil, vazia ou quebrada, ou a tabela que você salvou antes não era o que você pensava. Aqui está como encontrar qual é, e como decodificar com segurança.
1. A string é nil ou vazia
O caso mais comum. O valor que você decodifica não existe ainda:
- Uma coluna de banco de dados que é
NULL. Uma linha sem dados salvos retornanilpara essa coluna. - Uma query sem resultado.
MySQL.scalar.await(...)eMySQL.single.await(...)retornamnilquando nenhuma linha corresponde. Veja o guia de queries oxmysql para o que cada função retorna. - Uma chave KVP que nunca foi definida.
GetResourceKvpString('my_key')retornanilquando a chave não existe, veja KVP de recurso FiveM. - Um arquivo que está faltando.
LoadResourceFile(GetCurrentResourceName(), 'data.json')retornanilquando o arquivo não está lá. - Uma string vazia. Uma coluna salva como
''também não é um JSON válido.
Decodificar nil ou '' é um bug no chamador, então verifique a string primeiro:
local raw = GetResourceKvpString('my_key')
local data = {}
if raw and raw ~= '' then
data = json.decode(raw) or {}
end2. O JSON é inválido
Uma string que está presente ainda pode ser inválida. Causas típicas quando um arquivo ou um valor de banco de dados foi editado manualmente:
- Uma vírgula à direita após a última entrada:
{ "a": 1, } - Aspas simples em vez de duplas:
{ 'a': 1 } - Comentários no arquivo. JSON não permite.
- Um bracket ou aspas faltando após copiar parte de um arquivo.
- Sintaxe Lua colada em um arquivo JSON, como
a = 1ou[1] = 'x'. - Um caractere quebrado de um editor de texto, como aspas curvas copiadas de uma página da web.
{
"items": [
{ "name": "water", "count": 2 },
{ "name": "bread", "count": 1 }
]
}Valide o arquivo antes de culpar o script. VS Code sublinha erros JSON conforme você digita, e um validador JSON online mostra a posição exata do erro.
3. Sempre decodifique com pcall
Dependendo da entrada e da build, uma string ruim lança um erro Lua ou volta como nil. Você não precisa lembrar qual: coloque a chamada em uma função para ambos serem tratados.
local function safeDecode(str)
if type(str) ~= 'string' or str == '' then
return nil
end
local ok, result = pcall(json.decode, str)
if not ok or type(result) ~= 'table' then
return nil
end
return result
end
local data = safeDecode(row.metadata) or {}
print(data.level)A verificação type(result) ~= 'table' também captura um valor que é um JSON válido mas não é um objeto, como "hello" ou 5.
Dica: quando uma decodificação falha e você não sabe por quê, imprima a string bruta ao lado de seu tipo:
print(type(str), str). Umnilou uma linha vazia mostra a causa de imediato.
4. json.encode e as chaves que mudam
Uma decodificação pode funcionar e ainda lhe dar os dados errados, porque a tabela foi salva de uma forma que não sobrevive à viagem de ida e volta. JSON tem duas formas: uma lista [...] e um objeto {...} com chaves de texto.
local saved = json.encode({ [100] = 'a', [250] = 'b' })
local loaded = json.decode(saved)
print(loaded[100]) -- nil
print(loaded['100']) -- 'a'O que isso significa na prática:
- Chaves numéricas se tornam chaves de texto quando a tabela é salva como um objeto. Após a decodificação, procure o valor com a chave de texto, ou converta a chave com
tonumber. - Arrays esparsos com buracos (
{ [1] = 'a', [3] = 'c' }) não são uma lista limpa, então podem ser escritos como um objeto em vez de um array. - Tabelas mistas, com itens de lista e chaves nomeadas, não mapeiam nitidamente para nenhuma forma. Mantenha uma lista como uma lista, e coloque os campos nomeados em uma tabela separada.
- Funções, userdata e vetores não podem ser escritos como dados JSON simples. Converta um vetor para
{ x = v.x, y = v.y, z = v.z }antes de codificá-lo. - Uma tabela vazia é geralmente escrita como
[], então leia-a de volta como uma lista ou uma tabela vazia, não como um objeto.
Uma maneira segura de armazenar coordenadas:
-- save
local payload = json.encode({ x = coords.x, y = coords.y, z = coords.z })
-- load
local pos = safeDecode(payload)
if pos then
SetEntityCoords(ped, pos.x, pos.y, pos.z, false, false, false, false)
endUse json.encode(value, { indent = true }) enquanto depura, pois é muito mais fácil de ler.
5. Decodifique uma vez e verifique o tipo
Os dados de um banco de dados podem chegar ao seu script como uma string em um lugar e como uma tabela em outro. Algumas bibliotecas e frameworks decodificam colunas JSON para você, outras retornam o texto bruto. Antes de decodificar, verifique o que você tem:
local meta = row.metadata
if type(meta) == 'string' then
meta = safeDecode(meta)
end
meta = meta or {}Decodificar algo que já é uma tabela é um bug, e uma verificação de tipo não custa nada.
Lista de verificação
| Sintoma | Solução |
|---|---|
attempt to index a nil value (local 'data') após decodificação |
A string era nil ou inválida; verifique-a antes de decodificar e use pcall |
| Decodificação de uma coluna de banco de dados | NULL e resultados sem linha são nil; proteja com if raw and raw ~= '' |
| Uma leitura KVP não retorna nada | A chave nunca foi definida; use uma tabela padrão |
| Um arquivo editado manualmente falha | Remova vírgulas à direita, comentários e aspas simples; valide-o em um editor |
| Chaves numéricas perdidas após decodificação | As chaves JSON são texto; leia t['100'] ou converta com tonumber |
| Vetores escritos como JSON | Salve x, y e z como campos separados |
Respostas rápidas
Por que json.decode retorna nil ou lança um erro?
A string é nil, vazia, ou não é um JSON válido. Dependendo do caso, ela lança um erro ou não retorna nada, então coloque a chamada em pcall e verifique o resultado.
Por que minhas chaves numéricas são strings após json.decode?
As chaves de objeto JSON são sempre texto. Uma tabela como { [100] = true } é salva como um objeto com a chave de texto 100 e volta com a chave '100', então data[100] é nil.
Como verifico se um arquivo JSON é válido?
Abra-o em VS Code, que marca erros JSON no editor, ou cole-o em um validador JSON online. Os erros usuais são uma vírgula à direita, aspas simples ou um comentário.
Scripts sem esse problema
Item Creator V2Crie itens usáveis com animações, props, efeitos e muito mais — sem escrever código.Ver script →
Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →
Quest CreatorUm editor visual de missões e diálogos com NPCs, montado nó por nó dentro do jogo.Ver script →