Пример 1
Условие
Задан некоторый набор городов, привязанных к странам.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | CLASS Country 'Страна';
id 'Код' = DATA STRING[20] (Country) IN id;
name 'Имя' = DATA ISTRING[100] (Country) IN id;
country (STRING[20] id) = GROUP AGGR Country c BY id(c);
CLASS City 'Город';
name 'Имя' = DATA ISTRING[100] (City) IN id;
country 'Страна' = DATA Country (City);
nameCountry 'Страна' (City c) = name(country(c));
FORM cities 'Города'
OBJECTS c = City
PROPERTIES(c) name, nameCountry, NEW, DELETE
;
NAVIGATOR {
NEW cities;
}
|
Нужно отправить на определенный url HTTP-запрос на добавление города в формате JSON.
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | postCity 'Отправить' (City c) {
EXPORT JSON FROM countryId = id(country(c)), name = name(c);
LOCAL result = FILE();
EXTERNAL HTTP 'http://localhost:7651/exec?action=Location.createCity' PARAMS exportFile() TO result;
LOCAL code = STRING[10]();
LOCAL message = STRING[100]();
IMPORT JSON FROM result() TO() code, message;
IF NOT code() == '0' THEN {
MESSAGE 'Ошибка: ' + message();
}
}
EXTEND FORM cities
PROPERTIES(c) postCity
;
|
Оператор EXPORT создаст JSON в формате FILE и сохранит его в свойство exportFile. Пример сформированного файла :
{"countryId":"123","name":"San Francisco"}
Дальше вызывается оператор EXTERNAL, который делает запрос на предопределенный url, передавая туда в качестве Body содержимое сформированного файла. В данном случае, так как свойство в блоке FROM имеет тип JSON, то в качестве типа контента будет использоваться application/json. В url'е закодированы <пространство имен>.<имя свойства>. В данном случае пространство именем модуля вызываемого свойства createCity является Location. Все параметры передаются по порядку с идентификатором p. Ответ, который будет получен от сервера, будет записан в свойство result. Предположим, что ответ получен в формате JSON и имеет один из следующих видов :
{"code":"0","message":"OK"}
{"code":"1","message":"Некорректный код страны"}
Ответ разбирается при помощи оператора IMPORT, который раскладывает соответствующие параметры в свойства code и message соответственно. В случае ошибки пользователю выдается сообщение с текстом ошибки.
Пример 2
Условие
Аналогично Примеру 1.
Нужно принять соответствующий HTTP-запрос и создать новый город в базе данных с параметрами запроса.
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | createCity (FILE f) {
LOCAL cy = STRING[20] ();
LOCAL ne = STRING[100] ();
IMPORT JSON FROM f AS FILE TO() cy = countryId, ne = name;
IF NOT country(cy()) THEN {
EXPORT JSON FROM code = '1', message = 'Некорректный код страны';
RETURN;
}
NEW c = City {
name(c) <- ne();
country(c) <- country(cy());
APPLY;
}
EXPORT JSON FROM code = '0', message = 'OK';
}
|
Так как свойство имеет название createCity и расположено в модуле с пространством имен Location, то url, на котором будет принят запрос, имеет следующий вид :
http://localhost:7651/exec?action=Location.createCity
Body HTTP-запроса будет передан параметром с типом FILE. В локальные свойства cy и ne, считываются значения из параметров countryId и name соответственно.
Если не находится страна с соответствующим кодом, то формируется JSON файл с содержанием, описанном в предыдущем примере, и вызывается оператор RETURN, чтобы прервать выполнение. В качестве ответа, по умолчанию, используется значение, хранящееся в свойстве exportFile.
В случае, если все действия были завершены успешно, то формируется соответствующий ответ с сообщение ОК.
Пример 3
Условие
Задана логика заказов книг.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | CLASS Book 'Книга';
id 'Код' = DATA STRING[10] (Book) IN id;
name 'Наименование' = DATA ISTRING[100] (Book) IN id;
book (STRING[10] id) = GROUP AGGR Book b BY id(b);
CLASS Order 'Заказ';
date 'Дата' = DATA DATE (Order);
number 'Номер' = DATA STRING[10] (Order);
CLASS OrderDetail 'Строка заказа';
order 'Заказ' = DATA Order (OrderDetail) NONULL DELETE;
book 'Книга' = DATA Book (OrderDetail) NONULL;
nameBook 'Книга' (OrderDetail d) = name(book(d));
quantity 'Количество' = DATA INTEGER (OrderDetail);
price 'Цена' = DATA NUMERIC[14,2] (OrderDetail);
FORM order 'Заказ'
OBJECTS o = Order PANEL
PROPERTIES(o) date, number
OBJECTS d = OrderDetail
PROPERTIES(d) nameBook, quantity, price, NEW, DELETE
FILTERS order(d) == o
EDIT Order OBJECT o
;
FORM orders 'Заказы'
OBJECTS i = Order
PROPERTIES(i) READONLY date, number
PROPERTIES(i) NEWSESSION NEW, EDIT, DELETE
;
NAVIGATOR {
NEW orders;
}
|
Нужно отправить на определенный url HTTP-запрос на создание заказа в формате JSON.
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | FORM exportOrder
OBJECTS order = Order PANEL
PROPERTIES dt = date(order), nm = number(order)
OBJECTS detail = OrderDetail
PROPERTIES id = id(book(detail)), qn = quantity(detail), pr = price(detail)
FILTERS order(detail) == order
;
exportOrder 'Отправить' (Order o) {
EXPORT exportOrder OBJECTS order = o JSON;
LOCAL result = FILE();
EXTERNAL HTTP 'http://localhost:7651/exec?action=Location.importOrder' PARAMS exportFile() TO result;
}
EXTEND FORM orders
PROPERTIES(i) exportOrder;
;
|
Для создания JSON с вложенными тэгами нужно создать форму с соответствующими объектами, связанными через конструкцию FILTERS. На основе зависимостей между ними создается JSON с соответствующей структурой. В данном случае, JSON будет выглядеть следующим образом :
{ "dt":"20.08.18", "nm":"1", "detail":[ { "pr":5.99, "id":"b1", "qn":3 }, { "pr":6.99, "id":"b2", "qn":2 } ] }
Для order не создается свой тэг, так как значение объекта передается параметром для оператора EXPORT.
В данном примере, ответ полученный на HTTP-запрос игнорируется.
Пример 4
Условие
Аналогично Примеру 3.
Нужно принять соответствующий HTTP-запрос и создать новый заказ в базе данных с параметрами запроса.
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | date = DATA LOCAL DATE();
number = DATA LOCAL STRING[10]();
id = DATA LOCAL STRING[10] (INTEGER);
quantity = DATA LOCAL INTEGER (INTEGER);
price = DATA LOCAL NUMERIC[14,2] (INTEGER);
FORM importOrder
PROPERTIES dt = date(), nm = number()
OBJECTS detail = INTEGER
PROPERTIES id = id(detail), qn = quantity(detail), pr = price(detail)
;
importOrder (FILE f) {
IMPORT importOrder JSON FROM f;
NEW o = Order {
date(o) <- date();
number(o) <- number();
FOR id(INTEGER detail) DO NEW d = OrderDetail {
order(d) <- o;
book(d) <- book(id(detail));
quantity(d) <- quantity(detail);
price(d) <- price(detail);
}
APPLY;
}
}
|
Для импорта соответствующего файла в формате JSON создается форма аналогичной структуры, только в качестве классов объектов используется тип INTEGER. При импорте значения тэгов будут помещены в свойства с соответствующими именами. Свойства date и number не имеют параметров, так как в JSON значения для них идут на самом верхнем уровне.
Пример 5
Условие
Аналогично Примеру 4.
Нужно отправить на определенный url HTTP-запрос на создание заказа в формате JSON, аналогичный предыдущему примеру, только обернуть все в тэг order.
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | GROUP order;
FORM exportOrderNew
OBJECTS o = Order
PROPERTIES IN order dt = date(o), nm = number(o)
OBJECTS detail = OrderDetail IN order
PROPERTIES id = id(book(detail)), qn = quantity(detail), pr = price(detail)
FILTERS order(detail) == o
;
exportOrderNew 'Отправить (новый)' (Order o) {
EXPORT exportOrderNew OBJECTS o = o JSON;
LOCAL result = FILE();
EXTERNAL HTTP 'http://localhost:7651/exec?action=Location.importOrderNew' PARAMS exportFile() TO result;
}
EXTEND FORM orders
PROPERTIES(i) exportOrderNew;
;
|
В отличии от предыдущего примера создаем группу order, при помощи оператора GROUP. При объявлении формы в эту группу записываем все свойства для заказа и объект detail. Результирующий JSON будет выглядеть следующим образом :
{ "order":{ "dt":"20.08.18", "nm":"1", "detail":[ { "pr":5.99, "id":"b1", "qn":3 }, { "pr":6.99, "id":"b2", "qn":2 } ] } }
Пример 6
Условие
Аналогично Примеру 5.
Нужно принять соответствующий HTTP-запрос и создать новый заказ в базе данных с параметрами запроса.
Решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | FORM importOrderNew
PROPERTIES IN order dt = date(), nm = number()
OBJECTS detail = INTEGER IN order
PROPERTIES id = id(detail), qn = quantity(detail), pr = price(detail)
;
importOrderNew (FILE f) {
IMPORT importOrderNew JSON FROM f;
NEW o = Order {
date(o) <- date();
number(o) <- number();
FOR id(INTEGER detail) DO NEW d = OrderDetail {
order(d) <- o;
book(d) <- book(id(detail));
quantity(d) <- quantity(detail);
price(d) <- price(detail);
}
APPLY;
}
}
|
Точно также как и при экспорте, добавляем все свойств и объект detail в группу order для корректного приема новой версии JSON.
Пример 7
Условие
Аналогично Примеру 3.
Нужно по HTTP GET запросу, в котором задана дата, вернуть список номеров заказов от этой даты.
Решение
1 2 3 4 5 6 7 8 9 10 11 | FORM exportOrders
OBJECTS date = DATE PANEL
OBJECTS order = Order
PROPERTIES nm = number(order)
FILTERS date(order) = date
;
getOrdersByDate (DATE d) {
EXPORT exportOrders OBJECTS date = d JSON;
}
|
Url, на который следует слать HTTP запрос, будет выглядеть следующим образом : http://localhost:7651/exec?action=Location.getOrdersByDate&p=12.11.2018 .
В ответ будет возвращен, например, следующий JSON :
{ "order": [ { "nm": "42" }, { "nm": "65" } ] }