| # Especificaciones de JsonParserByLeo
|
|
|
| En este documento se presenta los siguientes puntos de JsonParserByLeo:
|
| - Garantias: que garantiza la lib, que valida, etc..
|
| - Casos (raros) en los cuales falla: Exacatmanete cual es el comportamiento de la liberia en ciertos casos.
|
| - Filosofica general: Como es que ha sido contruida esta lib
|
|
|
|
|
| ## Filosofia de diseño
|
| JsonParserByLeo al igual qeu todo el ecositema TSN, prioriza maxima velocida a un nivel (techo de MQL5)
|
| no nos conformamos con un "algortimo que es rapido" buscamos siempre la mejor forma en la que esto se pueda hacer en MQL5 puro,
|
| llegando al limite del lenguaje...
|
|
|
|
|
| JsonParserByLeo como tal no es una sola liberia JSON.. si no un conjunto de libs para trabajr con JSON en MQL5..
|
| pero el motor "principal" CJsonParser sigue el siguiente estilo:
|
| - DOM (Tape Style): se usa un array long[] para representar el "AST" del JSON
|
| - Eager: Materializa los numeros, booleanos, nulls, etc..
|
| - Lazy: Guarda offsets\len SOLO para keys y strings.
|
| - Solo lectura: No puedes modificar los campos.. solo es para leer un documento, pero puedes navegar tranquilamente o reeler el mismo nodo,
|
| es como la api de un dom (por ejemplo JAson
|
| en la cual peudes navegar tranquilamente, modifcar, etc) pero sin la posiblidad de modificar un nodo.
|
| > Nota: esto solo aplica a CJsonParser... se peude, apartir del tape llamar al backend de CJsonParser en especifico al dom builder
|
| > (CJsonNode::ToDom) para hacer un objeto en memoria el cual si que permite mutar completamente el JSON.
|
|
|
| Se podria decir que es una combinacino de DOM y OnDemanad usando el estilo tape (popuralizado por simdjson).
|
|
|
| ### Arquitectura en si
|
| Tome un par ideas prestadas de simdjson, en concreto estas ideas:
|
| 1. Uso de un tape para representar el documento json.
|
| 2. Algortimo para detectar el cierre de un string on manejo de escapes.
|
| > Asi que podriamos decir qeu esto no es un port o algo similar... Es en esencia agarrar un par de ideas de algo que funciona en general
|
| > luego aplicar un conocimiento del lengauje host (MQL5) tenicas, de optimzicion y estilo propio de hacer las cosas.. aqui en MQL5.
|
|
|
| Todo lo demas (stacks, algortimo de numeros, arquiteucta de como organizar
|
| las clases las herencias, JIT, algortimo de estados, etc etc) ha sido mi estilo propio o ideas que se me ocurrieron..
|
| en otros proyectos e integre aqui o cuando desarollaba este parser.
|
|
|
| ### JsonParserByLeo - (extras)
|
| JsonParserByLeo como tal no implemnta todo lo que promete en el README en este repositorio...
|
| Si no que usa el backend de BasesParserSLan (VM y DOM mutable) aqui.. en ese caso jsonparserbyleo
|
| solo "Transforma" su tape a ese formato.. y ya se integra.. tambien JsonPartserByLeo sirve como un ejemplo de uso
|
| de basesparserslan que es un framework que provee utilidades, dom, vm, etc.. para armar parsers de
|
| (base structured language) osea formatos estructurados como JSON, YAML, TOML, etc.., o un lenguaje custom...
|
| tambien se puede reutilizar ciertas partes para parsers mas especificos como .ini, o .rsp, etc..
|
|
|
| ## (Casos borde) - Resumen de areas
|
|
|
| ### Parsing (JsonAsm - Json - JsonSax)
|
|
|
| 1. **Integers**: if the limit is exceeded (`ULONG_MAX` for positive values, or `LONG_MIN` for negative values), the library understands that it is a big int, so it does not throw an overflow error; instead it stores it as a "string", and you can extract the result via `ToString()` with no loss.
|
| 2. **Reals**: this is split into the following layers:
|
| > - a) If the number can be represented properly, it is stored as-is as a `double`.
|
| > - b) The number already loses a little precision, but not much, it gets approximated.
|
| > - c) The number is large (for example, exponent > 22 or < -22, etc.) and gets promoted to a string. In `ToDouble`, the `StringToDouble` function is used, which is precise, so nothing is lost — it's just a heads-up about what happens. You can also retrieve it as a string.
|
| 3. **Keys**: Las keys no deberan de tener \" (commila en medio de la key es un caso muy raro) de lo contrario probacara comportamiento
|
| indefinido...
|
| > Si no controla la entrada puede usar: JSONPARSERBYLEO_ENABLE_ESCAPED_COMMILAS_IN_KEYS para activar su uso
|
|
|
| ### Unescape
|
| 1. **Keys**: En fucniones de acceso o trabajo con keys []\Get\Iteradores::Key\KeyToPosition\etc...
|
| El key no pasa por un proceso de desescapado (osea si tiene un key "\n") y intenta acceder por el valor \n real
|
| le dara un error de que no existe (empty node)... es un tradeoff que he tomado dado que casi nunca se tiene keys con escapes.. es algo raro..
|
| pero quizas a futuro pueda soportarlo via macros no por default,
|
| Nota que hay ciertas funciones como Query, VM Json.. estos si desescapan.. dado que son agnosticos a su implementacion..
|
| por lo tanto no pueden tomar esos tradeoffs.. pero fuera de eso.. ahi si.. no hay un desescapdo o verfiacion de key...
|
| > Por ahora la unica solucion es crear una funcion intermdia o envoler el nodo [] para que antes de llamarlo haga el unescape
|
| > para el unescape hay funciones que ya trae el backend de la lib como CJsonUnescape::Make*
|
| 2. **Algoritmo en si**: Dado que esto se resuelve on-demand en caso encontrar un escape invalido en el string
|
| la lib no tira error alguno en Parse()... donde si tira un error en cuando se intenta hacer la conversion
|
| en ToString(def), retornando def en caso de error, para surrogates invalidos por ahora a lib
|
| usa el caracter de remplzao no tira error.. si es necesario y en las siguientes versiones se pdoria integrar
|
| un bool o algo asi.
|
|
|
|
|
| ### `double` serialization (`CJsonBuilder`, `CJsonBuilderStr`, `CJsonDomSerializer`)
|
|
|
| 1. Si hay un valor (v) double el cual multiplicado por 10 (pow) digits
|
| ya no cabe en long , el resultado escrito no guarda relacion con el valor real.
|
| Ejemplo: `-1e25` con 16 decimales produce `-922.3372036854775808`. Con `digits = 8`, esto ocurre a partir de `v ≈ 9×10^10`.
|
| > Alternativa para apalear esto: Use ValSWV o PutRaw y use DoubleToString.
|
| 2. Parametro digits fuera de rango safe [0-22]: El serializador no valid si digits esta en dicho rango en cada acceso
|
| por lo que un valor invalido puede desencadenar un array out range....
|
| > Normalmente el numero de digitos se sabe en compilacion.. osea es una constante (tipicamente 8-12)
|
| Si es dinamico o es un valor que ud no controla agrege un cheking antes de setear el numero de digitos (o clamp).
|
| 3. Valores infinitos o nan: El serializador al no poder representarlos los escribe como null.
|
|
|
|
|
| ## Que garantizamos
|
| ### JSON Parser
|
| 1. Validacion estricta de numeros (leading zeros, buena formacino de E\e tambien de valores validos luego del . y e\E).
|
| 2. Validacion de true\false\null
|
| 3. Validacion de strings\keys cerrados correcamtne
|
| 4. Validacion gramatical mediante estados...(osea correcto orden)
|
| 5. Safe en casos borde (caracters invalidos dentro del json, validacion de cierre correcto de [,{ etc..)
|
|
|
| ### JSON Builder - Json Serializer
|
| Aparte de el problema mencionado con `double`, todo lo demas esta garantizado.. buena escritura de numeros, escape de caracters
|
| especiales, conservacion de utf8, manejo de emojis etc..
|
|
|
| ### JSON ASM
|
| al ser un formato custom creado por TSN-JsonParserByLeo este tiene sus propias reglas.
|
| - [Click aqui para ver el spec completo](./Src/ASM/README.md)
|
|
|