Błąd json.decode w FiveM: naprawy dla nil, pustych stringów i nieważnego JSON

json.decode nie działa lub zwraca nil w Twoim skrypcie FiveM? Dlaczego dekodowanie nil, pustego lub ręcznie edytowanego JSON się psuje, co json.encode robi z mieszanymi kluczami i jak bezpiecznie używać pcall.

Błąd pojawia się jeden wiersz po dekodowaniu:

text
SCRIPT ERROR: @my_script/server/main.lua:31: attempt to index a nil value (local 'data')
lua
local data = json.decode(row.metadata)
print(data.level)   -- data is nil

json.decode nie dał Ci nic użytecznego, więc następna linia zaindeksowała nil. Dekodowanie rzadko jest rzeczywistym błędem. Dane wejściowe były nil, puste lub zniszczone, lub tabela, którą zapisałeś wcześniej nie była tym, co myślałeś. Tutaj dowiesz się jak znaleźć który przypadek i jak dekodować bezpiecznie.

1. String to nil lub pusty

Najczęstszy przypadek. Wartość, którą dekoddujesz nie istnieje jeszcze:

  • Kolumna bazy danych, która jest NULL. Wiersz bez zapisanych danych zwraca nil dla tej kolumny.
  • Zapytanie bez wyniku. MySQL.scalar.await(...) i MySQL.single.await(...) zwracają nil gdy żaden wiersz się nie zgadza. Zajrzyj do oxmysql queries guide aby dowiedzieć się co każda funkcja zwraca.
  • Klucz KVP, który nigdy nie był ustawiony. GetResourceKvpString('my_key') zwraca nil gdy klucz nie istnieje, zobacz FiveM resource KVP.
  • Plik, który brakuje. LoadResourceFile(GetCurrentResourceName(), 'data.json') zwraca nil gdy plik tam nie jest.
  • Pusty string. Kolumna zapisana jako '' nie jest także ważnym JSON.

Dekodowanie nil lub '' to błąd w wywołującym, więc sprawdź string najpierw:

lua
local raw = GetResourceKvpString('my_key')
local data = {}

if raw and raw ~= '' then
    data = json.decode(raw) or {}
end

2. JSON jest nieważny

String, który jest obecny, może być wciąż nieważny. Typowe przyczyny gdy plik lub wartość bazy danych była edytowana ręcznie:

  • Przecinek na końcu po ostatnim wpisie: { "a": 1, }
  • Cudzysłowy jednokrotne zamiast podwójnych: { 'a': 1 }
  • Komentarze w pliku. JSON ich nie pozwala.
  • Brakujący nawias lub cudzysłów po skopiowaniu części pliku.
  • Składnia Lua wklejona do pliku JSON, taka jak a = 1 lub [1] = 'x'.
  • Zły znak z edytora tekstu, taki jak krzywe cudzysłowy skopiowane ze strony internetowej.
json
{
  "items": [
    { "name": "water", "count": 2 },
    { "name": "bread", "count": 1 }
  ]
}

Sprawdź plik przed tym, zanim obwinisz skrypt. VS Code podkreśla błędy JSON podczas pisania, a internetowy walidator JSON pokazuje dokładną pozycję błędu.

3. Zawsze dekoduj z pcall

W zależności od danych wejściowych i buildu, zły string albo podnosi błąd Lua, albo wraca jako nil. Nie musisz pamiętać które: opatrz wywołanie aby obsługiwane były oba.

lua
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)

Sprawdzenie type(result) ~= 'table' również chwyta wartość, która jest ważnym JSON ale nie obiektem, taką jak "hello" lub 5.

Wskazówka: gdy dekodowanie nie powiedzie się i nie wiesz dlaczego, wypisz surowy string obok jego typu: print(type(str), str). A nil lub pusta linia pokazuje przyczynę od razu.

4. json.encode i klucze, które się zmieniają

Dekodowanie może się powieść i wciąż dać Ci niepoprawne dane, ponieważ tabela została zapisana w formie, która nie przetrwa tam i z powrotem. JSON ma dwa kształty: listę [...] i obiekt {...} z tekstowymi kluczami.

lua
local saved = json.encode({ [100] = 'a', [250] = 'b' })
local loaded = json.decode(saved)

print(loaded[100])     -- nil
print(loaded['100'])   -- 'a'

Co to znaczy w praktyce:

  • Klucze liczbowe stają się kluczami tekstowymi gdy tabela jest zapisana jako obiekt. Po dekodowaniu, poszukaj wartości za pomocą tekstowego klucza, lub konwertuj klucz z tonumber.
  • Rzadkie tablice z dziurami ({ [1] = 'a', [3] = 'c' }) nie są czystą listą, więc mogą być napisane jako obiekt zamiast tablicy.
  • Mieszane tabele, zarówno z elementami listy jak i nazwanymi kluczami, nie mapują się czysty do żadnego kształtu. Przechowuj listę jako listę, i umieść nazwane pola w osobnej tabeli.
  • Funkcje, userdata i wektory nie mogą być napisane jako zwykłe dane JSON. Konwertuj wektor do { x = v.x, y = v.y, z = v.z } przed enkodowaniem.
  • Pusta tabela jest zwykle napisana jako [], więc przeczytaj ją z powrotem jako listę lub pustą tabelę, nie jako obiekt.

Bezpieczny sposób na przechowywanie współrzędnych:

lua
-- 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

Użyj json.encode(value, { indent = true }) podczas debugowania, ponieważ jest to o wiele łatwiejsze do przeczytania.

5. Dekoduj raz i sprawdzaj typ

Dane z bazy danych mogą dotrzeć do Twojego skryptu jako string w jednym miejscu i jako tabela w innym. Niektóre biblioteki i frameworki dekodują dla Ciebie kolumny JSON, inne zwracają surowy tekst. Zanim dekoddujesz, sprawdzaj co przechowujesz:

lua
local meta = row.metadata
if type(meta) == 'string' then
    meta = safeDecode(meta)
end
meta = meta or {}

Dekodowanie czegoś, co już jest tabelą, to błąd, a sprawdzenie typu nic nie kosztuje.

Checklist

Objaw Rozwiązanie
attempt to index a nil value (local 'data') po dekodowaniu String był nil lub nieważny; sprawdzaj go przed dekodowaniem i używaj pcall
Dekodowanie kolumny bazy danych NULL i brak wyników to nil; chrań z if raw and raw ~= ''
Odczyt KVP nic nie daje Klucz nigdy nie był ustawiony; używaj domyślnej tabeli
Ręcznie edytowany plik nie powiedzie się Usuń przecinki na końcu, komentarze i cudzysłowy jednokrotne; sprawdzaj go w edytorze
Klucze numeryczne stracone po dekodowaniu Klucze JSON to tekst; przeczytaj t['100'] lub konwertuj z tonumber
Wektory napisane jako JSON Zapisz x, y i z jako oddzielne pola

Szybkie odpowiedzi

Dlaczego json.decode zwraca nil lub rzuca błąd?

String to nil, pusty lub nieważny JSON. W zależności od przypadku albo podnosi błąd, albo nic nie zwraca, więc opatrz wywołanie w pcall i sprawdź wynik.

Dlaczego moje klucze liczbowe to stringi po json.decode?

Klucze obiektu JSON to zawsze tekst. Tabela taka jak { [100] = true } jest zapisywana jako obiekt z tekstowym kluczem 100 i wraca z kluczem '100', więc data[100] to nil.

Jak sprawdzić, czy plik JSON jest ważny?

Otwórz go w VS Code, który oznacza błędy JSON w edytorze, lub wklej do internetowego walidatora JSON. Zwykłe błędy to przecinek na końcu, cudzysłowy jednokrotne lub komentarz.

Skrypty bez tego problemu

Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →Quest CreatorWizualny edytor questów i dialogów z NPC, budowanych węzeł po węźle w grze.Zobacz skrypt →

Czytaj dalej