Haxe Code Cookbook
Haxe programming cookbookMacrosStrictly Typed JSON

Strictly Typed JSON

Reading time: 1 minute

It's possible read JSON files at compile time into strictly typed objects in Haxe.

Normally you might load a JSON file with something like this:

var json = haxe.Json.parse(sys.io.File.getContent(path));

Instead, if you load the JSON in a macro, then the JSON data will be available at compile time and therefore the types will be known:

Create a file called JsonMacro.hx (or whatever you like) and add this:

macro function load(path:String) {
    // Register a dependency to the external file so the Haxe compilation cache is invalidated if the file changes.
    haxe.macro.Context.registerModuleDependency(haxe.macro.Context.getLocalModule(), path);
    return try {
        var json = haxe.Json.parse(sys.io.File.getContent(path));
        macro $v{json};
    } catch (e) {
        haxe.macro.Context.error('Failed to load json: $e', haxe.macro.Context.currentPos());
    }
}

Then use this to load your JSON instead:

var leveldata = JsonMacro.load('leveldata.json');

for (i in leveldata.array) { // works now because we know the type of the leveldata object
}

Explanation: We run the original Json.parse(File.getContent()) snippet in a macro function so it will execute when Haxe compiles our calls to JsonMacro.load(). Instead of returning the JSON object, in macros we need to return syntax. So we must convert our JSON object into Haxe syntax – just as if we'd typed our JSON out manually as Haxe objects. Fortunately there's a built-in operator for converting values into Haxe syntax, it's the 'macro-reification-value-operator': $v{ some-basic-value }. We could also use Context.makeExpr(value, position) to do the same job. We wrap the JSON reading in a try-catch so we can tidy-up error reporting a little.

With this approach, the JSON's content is embedded into your compiled program and not loaded at runtime, therefore, the path argument must be a constant string and cannot be an expression evaluated at runtime.


Contributors:
Christian Zommerfelds
Last modified:
Created:
Category:  Macros