FiveM json.decode ошибка: nil, пустая строка и исправления невалидного JSON
json.decode падает или возвращает nil в вашем FiveM скрипте? Почему декодирование nil, пустых или отредактированных вручную JSON данных ломается, что делает json.encode с смешанными ключами, и как безопасно использовать pcall.
Ошибка появляется в строке после декодирования:
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 дал вам ничего полезного, поэтому следующая строка индексировала nil. Декодирование редко является настоящей причиной. Входная строка была nil, пустая или нарушена, или таблица, которую вы сохранили ранее, была не тем, что вы думали. Вот как найти что было не так, и как декодировать безопасно.
1. Строка это nil или пустая
Самый распространённый случай. Значение, которое вы декодируете, ещё не существует:
- Столбец базы данных это
NULL. Строка без сохранённых данных возвращаетnilдля этого столбца. - Запрос без результата.
MySQL.scalar.await(...)иMySQL.single.await(...)возвращаютnilкогда ни одна строка не совпадает. Смотрите oxmysql руководство запросов для того что возвращает каждая функция. - KVP ключ, который никогда не был установлен.
GetResourceKvpString('my_key')возвращаетnilкогда ключ не существует, смотрите FiveM resource KVP. - Файл, который отсутствует.
LoadResourceFile(GetCurrentResourceName(), 'data.json')возвращаетnilкогда файл там нет. - Пустая строка. Столбец сохранённый как
''тоже не является валидным JSON.
Декодирование nil или '' это ошибка вызывающей стороны, поэтому проверьте строку сначала:
local raw = GetResourceKvpString('my_key')
local data = {}
if raw and raw ~= '' then
data = json.decode(raw) or {}
end2. JSON невалидный
Строка, которая присутствует, может быть всё ещё невалидной. Типичные причины когда файл или значение базы данных было отредактировано вручную:
- Завершающая запятая после последней записи:
{ "a": 1, } - Одинарные кавычки вместо двойных:
{ 'a': 1 } - Комментарии в файле. JSON не допускает их.
- Отсутствующая скобка или кавычка после копирования части файла.
- Синтаксис Lua вставленный в JSON файл, такой как
a = 1или[1] = 'x'. - Нарушенный символ из текстового редактора, такой как кривые кавычки скопированные из веб-страницы.
{
"items": [
{ "name": "water", "count": 2 },
{ "name": "bread", "count": 1 }
]
}Валидируйте файл перед тем как винить скрипт. VS Code подчёркивает JSON ошибки во время ввода, и онлайн JSON валидатор показывает точную позицию ошибки.
3. Всегда декодируйте с pcall
В зависимости от входной строки и сборки, плохая строка либо вызывает Lua ошибку, либо возвращается как nil. Вам не нужно помнить какая: оберните вызов чтобы обработать оба случая.
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)Проверка type(result) ~= 'table' также ловит значение, которое является валидным JSON но не объектом, такой как "hello" или 5.
Совет: когда декодирование падает и вы не знаете почему, выведите сырую строку рядом с её типом:
print(type(str), str).nilили пустая строка показывает причину сразу.
4. json.encode и ключи, которые меняются
Декодирование может работать и всё ещё дать вам неправильные данные, потому что таблица была сохранена в форме, которая не переживает путешествие туда и обратно. JSON имеет две формы: список [...] и объект {...} с текстовыми ключами.
local saved = json.encode({ [100] = 'a', [250] = 'b' })
local loaded = json.decode(saved)
print(loaded[100]) -- nil
print(loaded['100']) -- 'a'Что это значит на практике:
- Числовые ключи становятся текстовыми ключами когда таблица сохраняется как объект. После декодирования, ищите значение с текстовым ключом, или конвертируйте ключ с
tonumber. - Разреженные массивы с дырами (
{ [1] = 'a', [3] = 'c' }) не являются чистым списком, поэтому они могут быть написаны как объект вместо массива. - Смешанные таблицы, как с элементами списка так и с именованными ключами, не отображаются чисто ни на одну форму. Держите список как список, и поместите именованные поля в отдельную таблицу.
- Функции, userdata и vectors не могут быть написаны как обычные JSON данные. Преобразуйте vector в
{ x = v.x, y = v.y, z = v.z }перед тем как вы закодируете его. - Пустая таблица обычно написана как
[], поэтому читайте её обратно как список или пустую таблицу, не как объект.
Безопасный способ сохранения координат:
-- 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)
endИспользуйте json.encode(value, { indent = true }) во время отладки, так как это намного легче читать.
5. Декодируйте один раз, и проверьте тип
Данные из базы данных могут дойти до вашего скрипта как строка в одном месте и как таблица в другом. Некоторые библиотеки и фреймворки декодируют JSON колонки для вас, другие возвращают сырой текст. Перед тем как вы декодируете, проверьте что вы держите:
local meta = row.metadata
if type(meta) == 'string' then
meta = safeDecode(meta)
end
meta = meta or {}Декодирование чего-то, что уже является таблицей, это ошибка, и проверка типа ничего не стоит.
Контрольный список
| Симптом | Решение |
|---|---|
attempt to index a nil value (local 'data') после декодирования |
Строка была nil или невалидной; проверьте её перед декодированием и используйте pcall |
| Декодирование столбца базы данных | NULL и результаты без строк это nil; охраните с if raw and raw ~= '' |
| Чтение KVP дает ничего | Ключ никогда не был установлен; используйте таблицу по умолчанию |
| Отредактированный вручную файл падает | Удалите завершающие запятые, комментарии и одинарные кавычки; валидируйте его в редакторе |
| Числовые ключи потеряны после декодирования | JSON ключи это текст; читайте t['100'] или конвертируйте с tonumber |
| Vectors написаны как JSON | Сохраняйте x, y и z как отдельные поля |
Короткие ответы
Почему json.decode возвращает nil или выбрасывает ошибку?
Строка это nil, пустая, или невалидный JSON. В зависимости от случая это либо вызывает ошибку, либо ничего не возвращает, поэтому оберните вызов в pcall и проверьте результат.
Почему мои числовые ключи становятся строками после json.decode?
JSON ключи объектов всегда текст. Таблица вроде { [100] = true } сохраняется как объект с текстовым ключом 100 и возвращается с ключом '100', поэтому data[100] это nil.
Как я могу проверить что JSON файл валидный?
Откройте его в VS Code, которые помечает ошибки JSON в редакторе, или вставьте в онлайн JSON валидатор. Обычные ошибки — это завершающая запятая, одинарные кавычки или комментарий.
Скрипты без этой проблемы
Item Creator V2Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →
Shop CreatorМагазин меньше чем за минуту — владельцы, сотрудники, сейфы и ограбления в комплекте.Смотреть скрипт →
Quest CreatorВизуальный редактор квестов и диалогов с NPC — узел за узлом прямо в игре.Смотреть скрипт →