Accessing data from an external JSON script. Need help accessing an array within a dictionary

Godot Version

4.4

Question

{
	"speaker-1": [
		{"name": "Darius"},
		{"lines": [
			{"line": "There is nothing else. We have reached the end","id": "s1l1"},
			{"id": "sll2", "line": "What else lies beyond the end, Penelope?"},
			{"id": "s1l3", "line": "We walk now to give Death an easier time."}
		]}
	],
	"speaker-2":[
		{"name": "Penelope"},
		{"lines": [  
			{"line": "We must keep moving forward.", "id": "s2l1"},
			{"id": "s2l2", "line": "No matter what."},
			{"id": "s2l3", "line": "They all await us . At the end."}
	]
		}
	]
}
extends Control

var my_data = preload("res://Scripts/script.json").data
var json = my_data
#var speaker_lines = FileAccess.get_file_as_string("res://Scripts/script.json")
var speaker_1 = json["speaker-1"]
var speaker_2 = json["speaker-2"]

func json_to_console() -> void:
	print(speaker_1["line"].to_string())
	print(speaker_2["line"].to_string())



func _on_button_pressed():
	json_to_console()

Good evening and or good morning. I’m very new to Godot and I’m having trouble with accessing data from an external JSON script. My long term goal is to feed dialogue lines from an external JSON script, but for now, I’m having trouble with accessing the array of “lines” from within the dictionary. With testing, I’ve tried to specify the first line of the array, but no luck so far. Any help would be amazing. Thanks in advance.

1 Like

Try:

func json_to_console() -> void:
    print(speaker_1["lines"][0]["line"].to_string())
1 Like

Didn’t work unfortunately, but I appreciate it. I still receive the error, "Invalid access to property or key “lines” on a base object of type “Array”

You have to follow the structure of your JSON data in order to access it.

If you want to print the first line of dialogue from speaker 1, then you want:

print(speaker_1[1]["lines"][0]["line"])

In generic terms, the shape of your data is as follows:

script_dictionary[speaker_number][array_index_pointing_to_lines_dictionary]["lines"][array_index_pointing_to_line_number]["line"]

If the example data you showed is consistent with the whole of your Script.json, then array_index_pointing_to_lines_dictionary will always be 1.

This seems like a pretty challenging data structure to work with, though. If you’re still in early days and have control over the shape of your data, I would recommend reconsidering this approach so that you have something easier to work with. If that isn’t an option and you prefer accessing the lines by their id, then you could try something like:

var speaker_1_lines = speaker_1[1]["lines"]
var line_index = speaker_1_lines.find_custom(func(line): return line["id"] == "s1l1")
print(speaker_1_lines[line_index]["line"])

Or to make that a bit more reusable:

func find_line_index(lines: Array, target_id: String) -> int:
	return lines.find_custom(func(line): return line["id"] == target_id)

# Then wherever you're trying to print the lines:
var speaker_1_lines = speaker_1[1]["lines"]
var line_index = find_line_index(speaker_1_lines, "s1l1")
print(speaker_1_lines[line_index]["line"])
1 Like

Thanks, I appreciate your help. I’ll try to find another way to structure my code so that it’s easier to access and utilize as I didn’t realize how many layers I currently have to access.

1 Like