Exporting project does not handle .json files as I had expected. How can I achieve what I want?

Godot Version

Godot_v4.5.1-stable_mono_win64

Question

My project has a bunch JSON files representing card info in my card game.
The file structure is as follows:

project_root/
    data/
        cards/
            some_card_1.json
            some_card_2.json
            ...
    src/
        GameData.cs

GameData.cs contains code responsible for loading the card info at runtime:

public class GameData
{
    ...

    public static List<Card> Cards { get; set; } = new(); 
    public static void Load()
    {
        var cardFiles = Directory.GetFiles("./data/cards/", "*.json");
        foreach (var cardFile in cardFiles)
        {
            var json = File.ReadAllText(cardFile);
            var card = JsonSerializer.Deserialize<Card>(json);
            if (card != null)
            {
                Cards.Add(card);
            }
            else
            {
                Log($"ERROR: Could not load card: {cardFile}");
                continue;
            }
            ...
        }
    ...
}

When I run my game in debug mode from the editor or from VSCode through my launch settings, it works fine.
But when I export a build for Windows, it seems I cannot get the exporter to copy the data folder.
I have added *.json to the “Filters to export non resourece files/folders” setting in the export dialog, but that doesn’t seem to do it.

  1. Could it be that my .JSON files are ending up in the .pck file? If so, is there another way I should read in the data?
  2. I have noticed that my exported build works fine when I manually copy the data folder into the folder with the .exe, is there a way to make the godot exporter copy my data folder?

Yes, this is what happens. You are adding non-resource “*.json” files to the pack. If you want to read files in the same directory as your executable you will need to use OS.get_executable_path()

Here’s a good stack overflow answer with more detail on the exact operations

If you only want to read your own json files then you can use paths starting with “res://”.

2 Likes

Yes, any resource under res:// ends inside the pck file. You can use DirAccess to list the files like for example: DirAccess.get_files_at("res://data/cards") and use FileAccess to read them.

You can make a plugin using a EditorExportPlugin.

Example:

@tool
extends EditorPlugin


func _enable_plugin() -> void:
	# Add autoloads here.
	pass


func _disable_plugin() -> void:
	# Remove autoloads here.
	pass


var export_plugin: ExportPlugin


func _enter_tree() -> void:
	export_plugin = ExportPlugin.new()
	add_export_plugin(export_plugin)


func _exit_tree() -> void:
	if is_instance_valid(export_plugin):
		remove_export_plugin(export_plugin)
		export_plugin = null


class ExportPlugin extends EditorExportPlugin:


	func _get_name() -> String:
		return "Export Plugin"


	func _export_begin(features: PackedStringArray, is_debug: bool, path: String, flags: int) -> void:
		var out_path = path.get_base_dir().path_join("data")
		var dir = DirAccess.open("data")
		dir.make_dir_recursive(out_path)
		for file in dir.get_files():
			dir.copy("data/%s" % file, out_path.path_join(file))



	func _export_file(path: String, type: String, features: PackedStringArray) -> void:
		if path.get_extension() == "json":
			skip()
1 Like

Thanks for your suggestions and explanations, they should help me solve this issue. I will post my experiences with them later when I get something working.

1 Like

I’m using .json files in Stahldrache for a similar purpose; each of my game objects (all the fighters, the missiles, the buildings…) has a json file describing them. I’ve got them in the pack file, and res:// links see them and load them just fine.