Libraries: JSON Serialization and Deserialization (native MQL) - page 3

 

Hi there!

Documentation of JAson library is not full at this site. I wrote documentation with more details and added unit tests: https://github.com/vivazzi/JAson. It may be useful for someone.

Add i created issue that has description of bug of using inner Json (CJAVal object): https://github.com/vivazzi/JAson/issues/1.

CJAVal object is not correctly assigned to another CJAVal object as object:

CJAVal data;

// simple structure
data["a"] = 12;

// nested structure
CJAVal nested_data;
nested_data["k1"] = 7;
nested_data["k2"] = "baz";

data["b"] = nested_data;

Print(data["b"]["k1"].ToInt());  // 0 instead of 7
Print(data["b"]["k2"].ToStr());  // "" instead of "baz"
Print(data.Serialize());  // {"a":12,"":{"k1":7,"k2":"baz"},"b":{}} instead of {"a":12,"b":{"k1":7,"k2":"baz"}}

As workaround, you need use Set() method:

data["b"].Set(nested_data);

Print(data["b"]["k1"].ToInt());  // 7
Print(data["b"]["k2"].ToStr());  // "baz"
Print(data.Serialize());  // {"a":12,"b":{"k1":7,"k2":"baz"}}

If anyone can help, then many MQL-developers will be grateful as this bug has been around for many years.

 
Артём Мальцев:

Hi there!

Documentation of JAson library is not full at this site. I wrote documentation with more details and added unit tests: https://github.com/vivazzi/JAson. It may be useful for someone.

Add i created issue that has description of bug of using inner Json (CJAVal object): https://github.com/vivazzi/JAson/issues/1.

CJAVal object is not correctly assigned to another CJAVal object as object:

As workaround, you need use Set() method:

If anyone can help, then many MQL-developers will be grateful as this bug has been around for many years.

The problem is with the Copy method. 

        virtual bool Copy(const CJAVal &a) {
            m_key=a.m_key;
            CopyData(a);
            return true;
    }

The key gets overwritten with the subobject's key in your example the "b" gets overwritten with the "nested_data"'s key which is empty. 

I used this simple solution, not fully tested: 

virtual bool Copy(const CJAVal &a) { if(m_key=="") m_key=a.m_key; CopyData(a); return true; }
 

Thank you, Laszlo Tormasi - your fix works and all tests have passed!

I updated JAson with your fixes: https://github.com/vivazzi/JAson

 
Json sample


{
  "id": 54,
  "nome": "12.01 alterado",
  "condicoes": [
    {
      "id": 47,
      "estrategiaId": 54,
      "indicadorAId": 87,
      "indicadorA": {
        "id": 87,
        "nome": "iATR",
        "parametros": [
          {
            "id": 46,
            "nome": null,
            "valor": 10.0
          }
        ]
      },
      "retornoA": 0,
      "comparador": ">",
      "indicadorBId": 88,
      "indicadorB": {
        "id": 88,
        "nome": "iAMA",
        "parametros": [
          {
            "id": 47,
            "nome": "Aplicar a",
            "valor": 1.0
          },
          {
            "id": 48,
            "nome": "Periodo rapido",
            "valor": 2.0
          },
          {
            "id": 49,
            "nome": "Periodo lento",
            "valor": 3.0
          },
          {
            "id": 50,
            "nome": "Deslocalmento",
            "valor": 4.0
          },
          {
            "id": 51,
            "nome": "Aplicar a",
            "valor": 0.0
          }
        ]
      },
      "retornoB": 0
    },
    {
      "id": 48,
      "estrategiaId": 54,
      "indicadorAId": 90,
      "indicadorA": {
        "id": 90,
        "nome": "iATR",
        "parametros": [
          {
            "id": 52,
            "nome": null,
            "valor": 10.0
          }
        ]
      },
      "retornoA": 0,
      "comparador": ">",
      "indicadorBId": 89,
      "indicadorB": {
        "id": 89,
        "nome": "iAMA",
        "parametros": [
          {
            "id": 53,
            "nome": "Aplicar a",
            "valor": 1.0
          },
          {
            "id": 54,
            "nome": "Periodo rapido",
            "valor": 2.0
          },
          {
            "id": 55,
            "nome": "Periodo lento",
            "valor": 3.0
          },
          {
            "id": 56,
            "nome": "Deslocalmento",
            "valor": 4.0
          },
          {
            "id": 57,
            "nome": "Aplicar a",
            "valor": 0.0
          }
        ]
      },
      "retornoB": 0
    }
  ]
}


I need get array of key "condicoes" 
  "condicoes": [ { "id": 47, ... } , { "id": 48, ... }]

My code mql

 

   string pJS=" ... " // Json Sample
   js.Deserialize(pJS);
   Print(js["nome"].ToStr()); // is correct = 12.01 alterado
   Print(js["condicoes"].m_type); // is correct type 6 or jtARRAY
   Print(js["condicoes"].Size()); //not work ... return 1, but correct 2

Can help me !?

Tanks

 
Andre Luiz Medeiros Peixoto #:
Json sample




I need get array of key "condicoes" 
  "condicoes": [ { "id": 47, ... } , { "id": 48, ... }]

My code mql

 


Can help me !?

Tanks

It works properly on my computer. How do you put the json string into the pJS variable? 

 

@Artem Maltsev Thank you for creating this JSON library. Is it based on some C++ library?

Do you have some performance benchmarks on this? Also, does it internally use 1 byte or 2 byte chars to store the data?

 

When a value is null, Deserialize() sets the type to jtNULL, but doesn't assign NULL to m_sv, so if ToStr() method is compared to NULL it returns false:

#include <JAson.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   string serialized="{\"a\":1,\"b\":null}";
   CJAVal json;
   json.Deserialize(serialized);
   if(json["b"].ToStr()==NULL)
   {
      Alert("b is NULL");
   }
   else if(json["b"].ToStr()=="")
   {
      Alert("b is an empty string");
   }
   else
   {
      Alert("b is ", json["b"].ToStr());
   }
}

The output is:

2022.03.28 17:50:02.833 test-jsonNULLComparison (GBPUSD,M30) Alert: b is an empty string

The workaround would be comparing the type of value to jtNULL or change the source code at line 220 by adding "m_sv=NULL;":

if (i+3<slen) if (StringCompare(GetStr(js, i, 4), "null", false)==0) { m_sv=NULL; i+=3; return true; }
 

Can you update Add some function likes

JAval j1; j1.Add(1);
j1["a"] = 1;
j1["b"] = 2;


can you Add this functions?

j1.Del("a");
j1.Pop();
j1.shift();
j1.sort();
j1.sort();
 
too many arguments for function-like macro 'DEBUG_PRINT_KEY' JAson.mqh 391 40
if (type != jtUNDEF) { DEBUG_PRINT_KEY(); return false; }  // if value already has type, then this is an error

   see declaration of macro 'DEBUG_PRINT_KEY' JAson.mqh

#ifdef DEBUG
    #define DEBUG_PRINT_KEY() Print(key+" "+string(__LINE__))
#else
    #define DEBUG_PRINT_KEY()
#endif

This warning is coming up on latest mql5 compilation

Any idea how to fix?

 
Arpit T #:
Any idea how to fix?

Remove the parenthesis

if (type != jtUNDEF) { DEBUG_PRINT_KEY; return false; }  // if value already has type, then this is an error
#ifdef DEBUG
    #define DEBUG_PRINT_KEY Print(key+" "+string(__LINE__))
#else
    #define DEBUG_PRINT_KEY
#endif
Reason: