FiveM json.decode Fehler: nil, leere Zeichenkette und ungültige JSON Behebung

json.decode schlägt fehl oder gibt nil in deinem FiveM-Skript zurück? Warum das Dekodieren von nil, leer oder manuell bearbeiteter JSON fehlschlägt, was json.encode bei gemischten Schlüsseln macht, und wie man pcall sicher nutzt.

Der Fehler erscheint eine Zeile nach dem Dekodieren:

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 gab dir nichts Verwendbares, also indexierte die nächste Zeile nil. Das Dekodieren ist selten der wirkliche Fehler. Die Eingabe war nil, leer oder beschädigt, oder die Tabelle, die du früher gespeichert hast, war nicht das, was du dachtest. Hier ist, wie man herausfinden kann, welcher Fall es ist, und wie man sicher dekodiert.

1. Die Zeichenkette ist nil oder leer

Der häufigste Fall. Der Wert, den du dekodierst, existiert noch nicht:

  • Eine Datenbankspalte, die NULL ist. Eine Zeile mit keinen gespeicherten Daten gibt nil für diese Spalte zurück.
  • Eine Query mit kein Ergebnis. MySQL.scalar.await(...) und MySQL.single.await(...) geben nil zurück, wenn keine Zeile passt. Siehe den oxmysql Queries Guide für was jede Funktion zurückgibt.
  • Ein KVP-Schlüssel, der niemals gesetzt wurde. GetResourceKvpString('my_key') gibt nil zurück, wenn der Schlüssel nicht existiert, siehe FiveM Ressourcen KVP.
  • Eine Datei, die fehlt. LoadResourceFile(GetCurrentResourceName(), 'data.json') gibt nil zurück, wenn die Datei nicht da ist.
  • Eine leere Zeichenkette. Eine Spalte, die als '' gespeichert ist, ist auch nicht gültiges JSON.

Das Dekodieren von nil oder '' ist ein Fehler des Aufrufers, daher überprüfe die Zeichenkette zuerst:

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

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

2. Das JSON ist ungültig

Eine anwesende Zeichenkette kann immer noch ungültig sein. Typische Ursachen, wenn eine Datei oder ein Datenbank-Wert manuell bearbeitet wurde:

  • Ein nachfolgendes Komma nach dem letzten Eintrag: { "a": 1, }
  • Einfache Anführungszeichen statt doppelter Anführungszeichen: { 'a': 1 }
  • Kommentare in der Datei. JSON erlaubt sie nicht.
  • Eine fehlende Klammer oder Anführungszeichen nach dem Kopieren von Teil einer Datei.
  • Lua-Syntax in eine JSON-Datei eingefügt, wie a = 1 oder [1] = 'x'.
  • Ein beschädigtes Zeichen von einem Text-Editor, wie gekrümmte Anführungszeichen von einer Webseite kopiert.
json
{
  "items": [
    { "name": "water", "count": 2 },
    { "name": "bread", "count": 1 }
  ]
}

Validiere die Datei, bevor du das Skript beschuldigst. VS Code unterstreicht JSON-Fehler, während du tippst, und ein Online-JSON-Validator zeigt die genaue Position des Fehlers.

3. Dekodiere immer mit pcall

Je nach Eingabe und Build wirft eine schlechte Zeichenkette entweder einen Lua-Fehler aus oder kommt als nil zurück. Du musst nicht merken, welcher: umhülle den Aufruf, damit beide behandelt werden.

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)

Der type(result) ~= 'table' Check fängt auch einen Wert, der gültiges JSON ist, aber kein Objekt, wie "hello" oder 5.

Tipp: wenn ein Dekodieren fehlschlägt und du nicht weißt, warum, drucke die rohe Zeichenkette neben ihrem Typ: print(type(str), str). Ein nil oder eine leere Zeile zeigt die Ursache sofort.

4. json.encode und die Schlüssel, die sich ändern

Ein Dekodieren kann funktionieren und dir immer noch die falschen Daten geben, weil die Tabelle in einer Form gespeichert wurde, die die Rundreise nicht überlebt. JSON hat zwei Formen: eine Liste [...] und ein Objekt {...} mit Text-Schlüsseln.

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

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

Was das praktisch bedeutet:

  • Numerische Schlüssel werden Textschlüssel, wenn die Tabelle als Objekt gespeichert wird. Nach dem Dekodieren schlage den Wert mit dem Textschlüssel auf, oder konvertiere den Schlüssel mit tonumber.
  • Sparse Arrays mit Lücken ({ [1] = 'a', [3] = 'c' }) sind keine saubere Liste, daher können sie als Objekt statt als Array geschrieben werden.
  • Gemischte Tabellen, mit sowohl Listengegenständen als auch benannten Schlüsseln, passen nicht sauber zu einer Form. Behalte eine Liste als Liste, und lege benannte Felder in einer separaten Tabelle.
  • Funktionen, Benutzerdaten und Vektoren können nicht als einfache JSON-Daten geschrieben werden. Konvertiere einen Vektor zu { x = v.x, y = v.y, z = v.z }, bevor du ihn kodierst.
  • Eine leere Tabelle wird normalerweise als [] geschrieben, daher lies sie als eine Liste oder eine leere Tabelle zurück, nicht als Objekt.

Ein sicherer Weg, um Koordinaten zu speichern:

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

Nutze json.encode(value, { indent = true }) beim Debuggen, da es viel leichter zu lesen ist.

5. Dekodiere einmal, und überprüfe den Typ

Daten aus einer Datenbank können dein Skript an einer Stelle als Zeichenkette und an einer anderen Stelle als Tabelle erreichen. Einige Bibliotheken und Frameworks dekodieren JSON-Spalten für dich, andere geben den rohen Text zurück. Bevor du dekodierst, überprüfe, was du hältst:

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

Das Dekodieren von etwas, das bereits eine Tabelle ist, ist ein Fehler, und eine Typüberprüfung kostet nichts.

Checkliste

Symptom Behebung
attempt to index a nil value (local 'data') nach dem Dekodieren Die Zeichenkette war nil oder ungültig; überprüfe sie vor dem Dekodieren und nutze pcall
Dekodieren einer Datenbankspalte NULL und No-Row-Ergebnisse sind nil; schütze mit if raw and raw ~= ''
Ein KVP-Lesen gibt nichts Der Schlüssel wurde niemals gesetzt; nutze eine Standard-Tabelle
Eine manuell bearbeitete Datei schlägt fehl Entferne nachfolgende Kommas, Kommentare und einfache Anführungszeichen; validiere es in einem Editor
Numerische Schlüssel nach dem Dekodieren verloren JSON-Schlüssel sind Text; lies t['100'] oder konvertiere mit tonumber
Vektoren als JSON geschrieben Speichere x, y und z als separate Felder

Kurze Antworten

Warum gibt json.decode nil zurück oder wirft einen Fehler?

Die Zeichenkette ist nil, leer oder nicht güliges JSON. Je nach Fall wirft sie einen Fehler oder gibt nichts zurück, daher umhülle den Aufruf in pcall und überprüfe das Ergebnis.

Warum sind meine numerischen Schlüssel nach json.decode Zeichenketten?

JSON-Objektschlüssel sind immer Text. Eine Tabelle wie { [100] = true } wird als Objekt mit dem Textschlüssel 100 gespeichert und kommt mit dem Schlüssel '100' zurück, also ist data[100] nil.

Wie überprüfe ich, dass eine JSON-Datei gültig ist?

Öffne sie in VS Code, die JSON-Fehler in dem Editor markiert, oder füge sie in einen Online-JSON-Validator ein. Die üblichen Fehler sind ein nachfolgendes Komma, einfache Anführungszeichen oder ein Kommentar.

Scripts ohne dieses Problem

Item Creator V2Erstelle nutzbare Items mit Animationen, Props, Effekten und mehr — ganz ohne Code.Script ansehen →Shop CreatorBau einen Shop in unter einer Minute — Besitzer, Angestellte, Tresore und Überfälle inklusive.Script ansehen →Quest CreatorEin visueller Editor für Quests und NPC-Dialoge, Node für Node im Spiel gebaut.Script ansehen →

Weiterlesen