A high-performance, memory-free JSON parser for MQL5, based on a flat tape architecture.<br/> Single-pass iterative state machine (as is, without extra loops, "pure" o(n)): no recursion, no dynamic memory fragmentation, no overhead from function calls.
2026-06-03 09:20:57 -05:00
</p>
---
## Main Features
- **Tape-based zero-alloc model**: the entire JSON is parsed into a single contiguous `long[]` array
- **Single flat loop**: one `switch` over a token enum, no helper function calls during parsing, strictly O(n)
2026-06-20 17:39:08 -05:00
- **JIT perfect-hash key lookup**: object access starts as linear probing (`StrEquals`); once a node passes `TSN_JSON_JIT_MIN_REF_TO_HASING` accesses, a minimal perfect hash table is built for it on the fly (`k = n`, no slack), promoting that node's lookups to O(1). No FNV hashing is computed upfront during parsing.
2026-06-03 09:20:57 -05:00
- **Handle-based navigation**: `CJsonNode` is a lightweight struct (pointer + two ints), copying is free
- **In-place mutation**: `SetInt`, `SetDbl`, `SetBool` modify the tape directly without re-parsing
- **Iterator support**: `CJsonIteratorObj` and `CJsonIteratorArray` for clean traversal
2026-06-20 17:39:08 -05:00
- **Three input formats, one API**: `AssingFile` auto-detects by extension — `.json` (plain text, needs `Parse()`), `.jsonasm` (assembly-like text dump of the tape, needs `ParseAssembly()`), `.jsontc` (precompiled binary tape, ready to use immediately, no parsing step)
- **Compiled tape cache (`.jsontc`)**: `SaveCompiled` persists the tape, the source JSON (or a reference to its file), and every perfect-hash table already built — so a reload via `AssingFile` skips parsing entirely and keeps any JIT-hashed nodes already O(1)
### Parse a `.jsonasm` file (text dump of the tape)
`AssingFile` detects the `.jsonasm` extension and loads the raw text — you still need to call `ParseAssembly()` (instead of `Parse()`) to turn it into a tape:
```mql5
TSN::CJsonParser parser;
parser.AssingFile("data.jsonasm", false);
2026-07-12 18:51:16 -05:00
parser.CorrectPadingForSwar();
2026-06-20 17:39:08 -05:00
parser.ParseAssembly();
TSN::CJsonNode root = parser.GetRoot();
```
You can also go the other way and dump an already-parsed tape into `.jsonasm` text (useful for debugging/inspecting the tape):
```mql5
uchar asm_text[];
parser.ToJsonAsm(asm_text);
Print(CharArrayToString(asm_text));
```
### Compile and reload a `.jsontc` tape cache
`SaveCompiled` writes the parsed tape (plus the source JSON and every perfect-hash table already built) to a binary `.jsontc` file. Reloading it via `AssingFile` skips parsing entirely:
```mql5
//--- Compile once
TSN::CJsonParser parser;
parser.Assing(my_json_string);
2026-07-12 18:51:16 -05:00
parser.CorrectPadingForSwar();
2026-06-20 17:39:08 -05:00
parser.Parse();
parser.GetRoot()["symbol"]; // (optional) warm up perfect-hash tables before saving
parser.SaveCompiled("data.jsontc", false);
//--- Reload later — no Parse()/ParseAssembly() needed, tape and hash tables are restored as-is
TSN::CJsonParser parser2;
parser2.AssingFile("data.jsontc", false);
TSN::CJsonNode root = parser2.GetRoot();
```
There's also an overload that stores a reference to an external JSON file instead of embedding it:
Requires the `tsndep` package, available on [PyPI](https://pypi.org/project/tsndep). It automatically downloads and installs all declared dependencies.
---
## Quick Start
**1. Include the library:**
```mql5
#include "..\\JsonParserByLeo\\Src\\JsonNode.mqh"
```
**2. Parse and access:**
```mql5
TSN::CJsonParser parser;
parser.Assing(my_json_string);
2026-07-12 18:51:16 -05:00
parser.CorrectPadingForSwar();
2026-06-03 09:20:57 -05:00
if(parser.Parse())
{
TSN::CJsonNode root = parser.GetRoot();
double price = root["price"].ToDouble(0.0);
}
```
**3. Re-parse without re-copying (benchmark pattern):**