Страница 1 из 18
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 16:34
Игорь Столяров
Привет всем !
Подскажите пожалуйста, как можно задать формат экспорта для вложенных структур данных ?
Демонстрационный пример:
Код: Выделить всё
MyDoc Group
Content String('Doc Content')
Review Group ! Упрощаем - здесь QUEUE
Content &String
end
end
Params &cJson
Code
MyDoc.Review.Content &= New(String(20)) ! Текст рецензии
MyDoc.Review.Content = 'Review Content'
Params &= json::CreateObject(MyDoc,,'[{{"name":"Review.Content","IsStringRef":true}]') ! Не работает для Review.Content
Params &= json::CreateObject(MyDoc,,'[{{"name":"Content","IsStringRef":true}]') ! Затирает значение MyDoc.Content
В реальных структурах часто повторяются имена полей в разных группах, пока удаётся задавать для них один тип данных ...
Спасибо !
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 17:00
Дед Пахом
Такой код
Код: Выделить всё
MyDoc GROUP
Content STRING('Doc Content')
Review GROUP
Content STRING('Review')
END
END
jParams &cJSON
Code
jParams &= json::CreateObject(MyDoc)
printd(jParams.ToString())
jParams.Delete()
и вывод: {"content":"Doc Content","review":{"content":"Review"}}
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 17:02
Дед Пахом
То есть я не совсем понял вопрос про один тип данных.
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 17:09
Дед Пахом
Понял. Ну тут надо слегка извернуться, внутреннему Content дать уникальное внешнее имя (ReviewContent), а в опциях вернуть оригинальное имя ("JsonName":"content"), тогда работает:
Код: Выделить всё
MyDoc GROUP
Content STRING('Doc Content')
Review GROUP
Content &STRING,NAME('ReviewContent')
END
END
jParams &cJSON
CODE
MyDoc.Review.Content &= NEW STRING(20)
MyDoc.Review.Content = 'Review'
jParams &= json::CreateObject(MyDoc,,'{{"name":"ReviewContent","JsonName":"content","IsStringRef":true}')
printd(jParams.ToString())
jParams.Delete()
DISPOSE(MyDoc.Review.Content)
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 18:11
Игорь Столяров
Дед Пахом писал(а): ↑17 Ноябрь 2022, 17:09
Ну тут надо слегка извернуться
Спасибо. До такого я сам бы не додумался. Но ! Я сам нашёл "IsStringRef", т.е. не безнадёжен ...
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 19:48
Дед Пахом
Дело слегка упрощается, если сразу объявлять поля с уникальными именами.
Код: Выделить всё
MyDoc GROUP
Content STRING('Doc Content')
Review GROUP
ReviewContent &STRING
END
END
jParams &cJSON
CODE
MyDoc.Review.ReviewContent &= NEW STRING(20)
MyDoc.Review.ReviewContent = 'Review'
jParams &= json::CreateObject(MyDoc,,'{{"name":"ReviewContent","JsonName":"content","IsStringRef":true}')
cJSON: Формат полей для вложенных структур
Добавлено: 17 Ноябрь 2022, 20:23
Игорь Столяров
Спасибо. Да, я уже понял, что кроме имени переменной, внешнего имени в Clarion, теперь есть ещё и JSON имя.
Это сильно упрощает формирование регистрозависимых запросов (например реестры в Сбер СБП).
cJSON: Формат полей для вложенных структур
Добавлено: 18 Ноябрь 2022, 12:17
Игорь Столяров
Ещё раз спасибо за "JsonName" - это многое меняет в качестве кода ... но есть вопрос.
Нет ли возможности групповой установки параметров полей ?
Поясню. Есть большие структуры описания документов, где для каждого вида документа выгружаются
общие поля и какой-то свой набор параметров. Причём поля надо именно исключать, а не паредавать пустые
(особенно указатели на вложенные списки). Т.е. что-то вроде (упрощённый концепт):
Код: Выделить всё
MyDoc GROUP
Name STRING(20)
Field01 Long
Field02 &Queue
Field02Instance Long
...
Field99 String(36)
end
jParams &cJSON
CODE
jParams &= json::CreateObject(MyDoc,,'{{"name":"_ALL_FIELD_","ignore":true},' & |
{{"name":"Name","ignore":False},{{"name":"Field45","ignore":False},{{"name":"Field64","ignore":False}')
!jParams.ToString() --> Выгрузили 3 поля: Name, Field45, Field64. Красота ведь ?
cJSON: Формат полей для вложенных структур
Добавлено: 18 Ноябрь 2022, 18:07
Дед Пахом
В принципе звёздочка (вместо _ALL_FIELD_) есть: "name" : "*". Но она задумывалась для случаев, когда задаются свойства для всех полей без исключения. Надо бы исправить функцию FindFieldRule, попробуйте такой вариант, если норм, то я обновлю:
Код: Выделить всё
FindFieldRule PROCEDURE(STRING fldName, *TFieldRules rules)
qIndex LONG, AUTO
CODE
!- search for a rule for fldName
LOOP qIndex = 1 TO RECORDS(rules)
GET(rules, qIndex)
IF LOWER(rules.Name) = LOWER(fldName)
!- found
RETURN
END
END
!- no rules found for fldName, search for a generic rule
LOOP qIndex = 1 TO RECORDS(rules)
GET(rules, qIndex)
IF rules.Name = '*'
!- found
RETURN
END
END
!- no rules found
CLEAR(rules)
cJSON: Формат полей для вложенных структур
Добавлено: 18 Ноябрь 2022, 23:35
Дед Пахом
Хотя надо ещё подумать, этот вариант не совсем то.
cJSON: Формат полей для вложенных структур
Добавлено: 18 Ноябрь 2022, 23:48
Игорь Столяров
Всегда готов потестировать !
- sm166.gif (6.69 КБ) 1855 просмотров
cJSON: Формат полей для вложенных структур
Добавлено: 20 Ноябрь 2022, 0:24
Игорь Столяров
Если я правильно понял правила работы правил (не факт), то вопрос решается вот так:
Код: Выделить всё
FindFieldRule PROCEDURE(STRING fldName, *TFieldRules rules)
qIndex LONG, AUTO
sIndex Long(0) ! Номер крайнего правила для поля
CODE
LOOP qIndex = 1 TO RECORDS(rules)
GET(rules, qIndex)
IF LOWER(rules.Name) = LOWER(fldName) OR rules.Name = '*'
!- found field rules
sIndex = qIndex !RETURN
END
END
!- not found field rules
If sIndex = 0 then CLEAR(rules)
else
Get(rules,sIndex)
end
Получилось даже лучше, чем хотел.
Код: Выделить всё
MyDoc GROUP
Name STRING(20)
Field01 Long
Field02 &Queue
Field02Instance Long
...
Field99 String(36)
end
jParams &cJSON
CODE
jParams &= json::CreateObject(MyDoc,,'{{"name":"*","ignore":true},' & |
{{"name":"Name","ignore":False},{{"name":"Field01","IsBool":True},{{"name":"Field02","IsQueue":True}')
!jParams.ToString() --> Выгрузили 3 поля: Name, Field01, Field02 (массив).
Т.е. наличие для поля ЛЮБОГО индивидального правила, отключает для этого поля ВСЕ предыдущие общие правила.
Проверьте пожалуйста моё кустарное производство.
cJSON: Формат полей для вложенных структур
Добавлено: 20 Ноябрь 2022, 0:35
Дед Пахом
В Вашем варианте порядок появления правил играет существенную роль. Я на такое не пойду.
cJSON: Формат полей для вложенных структур
Добавлено: 20 Ноябрь 2022, 7:55
Игорь Столяров
Спасибо - понял. Но направление выбрано верное ?
Релиз 2.0: Разделяем правила и применяем общее только если нет индивидуального.
Код: Выделить всё
FindFieldRule PROCEDURE(STRING fldName, *TFieldRules rules)
qIndex LONG, AUTO
GeneralRule Long(0)
CODE
LOOP qIndex = 1 TO RECORDS(rules)
GET(rules, qIndex)
If LOWER(rules.Name) = LOWER(fldName)
RETURN ! Individual rule for the field
elsIf rules.Name = '*'
GeneralRule = qIndex
end
END
If GeneralRule > 0 then Get(rules,GeneralRule) ! General rule for the field
else
Clear(rules) !- not found field rules
end
Теперь порядок правил не имеет значения, но приоритет у индивидуального:
Код: Выделить всё
jParams &= json::CreateObject(MyDoc,,'{{"name":"Name","ignore":False},{{"name":"*","ignore":true},{{"name":"Field02","IsQueue":True}')
! Выгружает только поля: Name и Field02 (как массив)
cJSON: Формат полей для вложенных структур
Добавлено: 20 Ноябрь 2022, 12:09
Дед Пахом
Так лучше, но тогда общие правила полностью игнорируются индивидуальными. Пример:
- все поля трактовать как bool
- поле "Expired" переименовать в "IsExpired"
тогда общее правило будет
{"name"="*", "isbool":true}
индивидуальное правило
{"name"="Expired", "jsonname":"IsExpired"}
В Вашем случае isbool не сработает для поля Expired.
Я хочу, чтобы сначала применялись правила для поля, а затем общее правило. То есть если правило
{"name"="Expired", "jsonname":"IsExpired"}
то isbool (true) подтягивается из общего, а если
{"name"="Expired", "jsonname":"IsExpired", "isbool":false}
то применяется явное false.