Json в mql: JAson

22 марта 2021 г. 21:32

В MQL нет возможности хранить данные различных типов через стандартные типы данных, как это можно сделать в python через словари или в javascript через объекты. Так как MQL типизированный язык, то реализация данных в виде словаря, где хранятся данные в виде пар "ключ - значение", весьма трудоёмко. К счастью, есть замечательная библиотека JAson, которая позволяет хранить данные различных типов в виде словаря, а если быть точнее, то в виде JSON. Также библиотека преобразовывать JSON объект в виде строки и обратно.

Код библиотеки можно найти на странице mql5.com/ru/code/13663. Так как библиотека не находится в каком-либо репозитории, то во-первых, сложно следить за обновлениями, а во-вторых, произвести автоматизацию по обновлению этой библиотеки у себя на рабочей машине, поэтому я выложил её к себе в репозиторий, добавив документацию (которой изначально особо не было), юнит-тесты и небольшие исправления.

Библиотека JAson находится на github по ссылке:
https://github.com/vivazzi/JAson

Установка

Скачайте (склонируйте) репозиторий и скопируйте JAson/Include/JAson.mqh в папку <TERMINAL DIR>/MQL(4/5)/Include.

Использование

Добавьте #include <JAson.mqh> и создайте CJAVal объект для работы с JSON. Для быстрого понимания посмотрите этот пример:

#include <JAson.mqh>

int OnInit(){
    CJAVal data;

    // --- simple structure ---
    data["a"] = 12;
    data["b"] = 3.14;
    data["b"] = "foo";
    data["d"] = true;

    Print(data["a"].ToInt());  // 12
    Print(data["b"].ToDbl());  // 3.14
    Print(data["c"].ToStr());  // "foo"
    Print(data["d"].ToBool());  // true

    // --- array structure ---
    data["e"].Add("bar");
    data["e"].Add(2);
    
    Print(data["e"][0].ToStr());  // "bar"
    Print(data["e"][1].ToInt());  // 2
    
    // --- nested structures ---
    // - as part of array -
    CJAVal sub_data_obj_in_list;
    sub_data_obj_in_list["k1"] = 7;
    sub_data_obj_in_list["k2"] = "baz";
    
    data["e"].Add(sub_data_obj_in_list);
    
    Print(data["e"][2]["k1"].ToInt());  // 7
    Print(data["e"][2]["k2"].ToStr());  // "baz"
    
    // - as object -
    CJAVal sub_data_obj;
    sub_data_obj["sub_c"] = "muz2";
    sub_data_obj["sub_d"] = 44;

    data["f"].Set(sub_data_obj);
    Print(data["f"]["sub_c"].ToStr());  // "muz2"
    Print(data["f"]["sub_d"].ToInt());  // 44
}

Внимание: чтобы присвоить другой CJAVal объект к текущему по какому-то ключу, используйте метод Set() вместо прямого присваивания через знак =, иначе текущий CJAVal объект не сохранить ключ, а точнее сохранит вложенные данные с пустым ключом.
Подробнее в тикете: https://github.com/vivazzi/JAson/issues/1

Для получения значения из CJAVal объекта используйте методы:

  • ToInt() для integer
  • ToDbl() для double
  • ToStr() для string
  • ToBool() для boolean

Например:

data["a"].ToInt();  // 12
data["b"].ToDbl();  // 3.14
data["c"].ToStr();  // "foo"
data["d"].ToBool();  // true

Для создания массива используйте .Add():

data["e"].Add("bar");
data["e"].Add(2);

Для использования вложенного json, создайте другой CJAVal объект и присвуйте к существующему CJAVal объекту. Вложенный CJAVal объект может быть значением ключа или содержаться в массиве:

CJAVal data;

// - adding as object -
CJAVal data_1;
data_1["d1_1"] = 7;
data_1["d1_2"] = "foo";

data["a"].Set(data_1);

// - adding as part of array -
CJAVal data_2;
data_2["d2_1"] = 1;
data_2["d2_1"] = "bar";

data["b"].Add("buz");
data["b"].Add(data_2);
data["b"].Add("muz");

Сериализация и десериализация

JAson обеспечивает сериализацию и десериализацию:

#include <JAson.mqh>

int OnInit(){
    string data_str;
    CJAVal data;

    data["a"] = 3.14;
    data["b"] = "foo";
    data["c"].Add("bar");
    data["c"].Add(2);
    data["c"].Add("baz");

    Print(data["b"].ToStr());  // foo
    
    data_str = data.Serialize();
    Print(data_str);  // {"a":3.14000000,"b":"foo","c":["bar",2,"baz"]}
    
    CJAVal data_2;
    data_2.Deserialize(data_str);
    
    Print(data_2["a"].ToDbl());  // 3.14
    Print(data_2["b"].ToStr());  // foo
    
    Print(data_2["c"][0].ToStr());  // bar
    Print(data_2["c"][1].ToInt());  // 2
    Print(data_2["c"][2].ToStr());  // baz
}

Это может быть полезно для сохранения данных в файл, например, для хранения исторических данных или взаимодействия между терминалами или экспертами. Также это может быть полезно для взаимодействия с интернет ресурсами.

Пример: POST запрос с Json:

#include <JAson.mqh>
#include <requests/requests.mqh>  // https://github.com/vivazzi/mql_requests

int OnInit(){
    CJAVal data;

    data["a"] = 7;
    data["b"] = "foo";
    
    Requests requests;
    Response response = requests.post("https://vivazzi.pro/test-request/", data.Serialize());
    
    Print(response.text);  // {"status": "OK", "method": "POST", "body": "{"a": 7, "b": "foo"}"}
    data.Deserialize(response.text);
    
    Print(data["status"].ToStr());  // "OK"
    Print(data["method"].ToStr());  // "POST"
    Print(data["body"].ToStr());  // {"a": 7, "b": "foo"}
    
    // if Json object has value of key as serialized object, you can also deserialize this value
    CJAVal data_2;
    data_2.Deserialize(data["body"].ToStr());
    Print(data_2["a"].ToInt());  // 7
    Print(data_2["b"].ToStr());  // "foo"
    
    // also you can join this Json objects to get full structure
    data["body"].Set(data_2);
    Print(data["body"]["a"].ToInt());
    Print(data["body"]["b"].ToStr());
}

В этом примере была использована библиотека mql_requests и Getest - сервис для тестирования запросов.

Clear Json and check for the existence of a key

Для очистки CJAVal объекта, используйте метод Clear():

#include <JAson.mqh>

int OnInit(){
    CJAVal data;
    string data_str;

    data["a"] = 3.14;
    data["b"] = "foo";
    data_str = data.Serialize();
    Print(data_str);  // "{"a":3.14000000,"b":"foo"}"

    data.Clear();
    data["c"] = 123;
    data["d"] = "bar";
    data_str = data.Serialize();
    Print(data_str);  // "{"c":123,"d":"bar"}"
}

Таким образом, получить значения ключей "c" и "d" можно так:

Print(data["c"].ToInt()) // 123
Print(data["d"].ToStr()) // "bar"

Но если проверить ключи "a" и "b", которые больше не существуют, или проверить никогда не использованные ключи, то вы получите значения по умолчанию:

// old notexistent keys
Print(data["a"].ToDbl())  // 0.0
Print(data["b"].ToStr())  // "" (empty)

// never used keys
Print(data["e"].ToStr())  // "" (empty)

И это может привести к логическим ошибкам - будьте осторожны! Всегда используйте определённый набор ключей, чтобы избечать логических ошибок!

Если вы используйтете JSON, который может быть очищен, или используете различные ключи, вы можете проверить тип ключа. JAson библиотека определяет следующие типы ключей:

  • jtUNDEF, если ключ не определён
  • jtNULL для NULL
  • jtBOOL для boolean
  • jtINT для int
  • jtDBL для double
  • jtSTR для string
  • jtARRAY для array
  • jtOB для obj

Тогда в примере выше можно опредлить типы:

// old notexistent keys
Print(data["a"].ToDbl());  // 0.0
Print(data["a"].m_type);  // jtUNDEF
Print(data["b"].ToStr());  // ""
Print(data["b"].m_type);  // jtUNDEF

// current keys
Print(data["c"].ToInt());  // 123
Print(data["c"].m_type);  // jtINT
Print(data["d"].ToStr());  // "bar"
Print(data["d"].m_type);  // jtSTR

// never used keys
Print(data["e"].ToStr());  // ""
Print(data["e"].m_type);  // jtUNDEF

Таким образом, вы можете сравнивать тип ключа с jtUNDEF, чтобы проверить существование ключа:

#include <JAson.mqh>

int OnInit(){
    CJAVal data;

    data["a"] = 3.14;

    data.Clear();
    data["c"] = 123;
    
    if (data["a"].m_type == jtUNDEF) {
        // do something
    } else {
        // else do something
    }
}

API

CJAVal data; - Создаёт CJAVal (Json) объект

data[key] = some_val; - Добавляет some_val (int, double, string) в data с ключём key
data[key].Add(other_data); - Добавляет other_data (int, double, string или другой CJAVal) к ключу массива
data[key].Set(other_data); - Присваивает other_data CJAVal объект к data объекту с определённым ключём key

data.Clear(); - Очищает CJAVal объект
data.Size(); - Возвращает размер CJAVal объекта

Библиотека JAson находится на github по ссылке:
https://github.com/vivazzi/JAson

Оцените статью

0 из 5 (всего 0 оценок)

captcha
Отмеченные звёздочкой поля ( * ) являются обязательными для заполнения.

Спасибо за ваш отзыв!

После нажатия кнопки "Отправить" ваше сообщение будет доставлено мне на почту.

Автор статьи

Права на использование материала, расположенного на этой странице https://vivazzi.pro/it/json-mql/:

Разрешается копировать материал с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор статьи: Мальцев Артём
Ссылка на статью: <a href="https://vivazzi.pro/it/json-mql/">https://vivazzi.pro/it/json-mql/</a>

Подробнее: Правила использования сайта

Комментариев: 0

Вы можете оставить комментарий как незарегистрированный пользователь.

Но зарегистрировавшись, вы сможете:

  • получать оповещения об ответах
  • просматривать свои комментарии
  • иметь возможность использовать все функции разработанных сервисов

Для комментрирования от своего имени, войдите или зарегистрируйтесь обычным способом или через социальные сети:

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте

Выберите валюту для отображения денежных единиц