Ah, I think I misunderstood how you were you using the JSON. The JSON isn’t the entire grammar, just the “terminals” — the strings themselves, tagged to indicate the role they fill.
You could treat the root object in the JSON file as the grammar object itself, with the attributes themselves representing the rules in the grammar. Still, that’s not quite what you had, and might not be trivial to convert your code into that.
Sorry I misunderstood! I still think you were pretty close to a working hard-mode implementation, though. :)