Страница 1 из 2

cJSON: Метод ToGroup() и списки

Добавлено: 06 Октябрь 2024, 19:24
Игорь Столяров
Добрый день !
v1.47 (06.10.2024): ToGroup internally calls json::DeepClear.
Если позволите - ещё один старый вопрос, который сильно ухудшает качество кода.
Смотрим первые две строчки в штатном примере QueueInGroupTest.clw
CODE
!- initialize queue references
PersonGrp.Addresses &= AddressQ
PersonGrp.Phones &= PhonesQ
Но ведь это обман ... ;) Ну или абсолютно пустое действие - эти указатели будут сразу затёрты ToGroup()
и любое обращение к ним закончится мусором или GPF.

На стороне метода ToGroup() есть имена полей с указателями списков и собственно сами указатели.
Почему нельзя после очистки GROUP сразу восcтановить обратно указатели на списки и сохранить
инициализацию вложенных списков в GROUP ?

Код: Выделить всё

  PersonGrp.Addresses  &= (Addr::Inst)
  PersonGrp.Phones     &= (Phones::Inst)
Спасибо за рассмотрение вопроса. :)

cJSON: Метод ToGroup() и списки

Добавлено: 06 Октябрь 2024, 22:21
Дед Пахом
Было CLEAR, теперь json::DeepClear, принципиально ничего не изменилось. Хотите обновлённый штатный пример QueueInGroupTest.clw?

cJSON: Метод ToGroup() и списки

Добавлено: 06 Октябрь 2024, 22:33
Игорь Столяров
Нет. Я спрашиваю можно ли в методе ToGroup() восстанавливать указатели на вложенные списки
после выполнения json::DeepClear (ранее CLEAR). :)

cJSON: Метод ToGroup() и списки

Добавлено: 06 Октябрь 2024, 22:58
Дед Пахом
Посмотрим.

cJSON: Метод ToGroup() и списки

Добавлено: 07 Октябрь 2024, 22:14
Дед Пахом
А давайте вы напишете, чё всё я.

cJSON: Метод ToGroup() и списки

Добавлено: 08 Октябрь 2024, 1:49
Admin
Дед Пахом писал(а): 07 Октябрь 2024, 22:14 А давайте вы напишете, чё всё я.
Ахаха. Пора принимать пулл реквесты!

cJSON: Метод ToGroup() и списки

Добавлено: 08 Октябрь 2024, 13:57
Игорь Столяров
Дед Пахом писал(а): 07 Октябрь 2024, 22:14 А давайте вы напишете, чё всё я.
Это батл ! :) Хотя кого я пытаюсь обмануть, здесь работы на 15 минут даже для меня ... ;)

Предположим, я хочу засабклассить метод ToGroup() что бы он не затирал указатели на вложенные списки.
(*) - Маленькое допущение: что бы не замыливать идею - я не буду копировать сюда код распарса Options.

Код: Выделить всё

ToGroup  PROCEDURE(STRING pJson, *GROUP pGrp, BOOL pMatchByFieldNumber = FALSE, <STRING pOptions>) !, BOOL, PROC
BRetVal  Bool
Json     cJSONFactory
fldRef   ANY, AUTO
i        LONG, AUTO

qSaveList Queue
Number      Long
FldList     Any
          end
  Code
  
  ! Сохраняем указатели на вложенные списки в pGrp
  LOOP i=1 TO 99999
    fldRef &= WHAT(pGrp, i)
    IF fldRef &= NULL then Break.

   !If fldRule.Instance    ! (*) Здесь фильтр по наличию тега "Instance" в Options для поля в pGrp    
    If InRange(i,2,3)  
    
       Clear(qSaveList)
       qSaveList.Number  = i
       qSaveList.FldList = fldRef
       Add(qSaveList)  
    end
  end  
  
  ! Собственно вызываем SELF метод для распарса
  BRetVal = Json.ToGroup(pJson, pGrp, pMatchByFieldNumber, pOptions)
  
  ! И восстанавливаем указатели на вложенные списки в pGrp
  Loop i = Records(qSaveList) to 1 by -1
    Get(qSaveList,i)
    
    ! Если в pGrp есть поле с номером qSaveList.Number -> восстановить указатель на список
    fldRef &= WHAT(pGrp, qSaveList.Number)        
    If Not fldRef &= NULL then fldRef = qSaveList.FldList. 
       
    qSaveList.FldList &= Null  ! Очистка ANY поля
    Delete(qSaveList)
  end  
  
  Return BRetVal
И вот теперь да, мы можем без GPF работать с вложенными списками в любезно представленном Вами примере:

Код: Выделить всё

TestPublic  Routine
  Data
Parser  cJSONFactory

!- json string
testString                      STRING('{{"name": "Carl", "addresses": [{{"city": "Rivercity","street": "Main st","house": 123},{{"city": "Rivertown","street": "Park st","house": 987}], "phones": ["1234567", "7654321"]}')

TypeAddressQ                    QUEUE,Type
City                              STRING(20)
Street                            STRING(20)
House                             LONG
                                END
!- address queue
AddressQ                        QUEUE(TypeAddressQ).

!- phone queue
TypePhonesQ                     QUEUE,Type
Phone                             STRING(20)
                                END

PhonesQ                         QUEUE(TypePhonesQ).

!- person group
PersonGrp                       GROUP
Name                              STRING(20)
Addresses                         &TypeAddressQ  !- reference to AddressQ
Phones                            &TypePhonesQ   !- reference to PhonesQ
                                END

Addr::Inst                      LONG, AUTO    !- INSTANCE(AddressQ, THREAD())
Phones::Inst                    LONG, AUTO    !- INSTANCE(PhonesQ, THREAD())


qIndex                          LONG, AUTO

  CODE
  !- initialize queue references
  PersonGrp.Addresses &= AddressQ
  PersonGrp.Phones &= PhonesQ
    
  !- read instances of queues in this thread
  Addr::Inst = INSTANCE(AddressQ, THREAD())
  Phones::Inst = INSTANCE(PhonesQ, THREAD())
  
  !- parse json
  If ToGroup(testString, PersonGrp, FALSE, '[{{"name":"Phones", "instance":'& Phones::Inst &'},{{"name":"Addresses", "instance":'& Addr::Inst &'}]')

     !- check result
     MESSAGE('Name: '& PersonGrp.Name)
  
  ! РАБОТАЕМ СО СПИСКАМИ В ГРУППЕ !!!
  LOOP qIndex = 1 TO RECORDS(PersonGrp.Addresses)
    GET(PersonGrp.Addresses, qIndex)
    MESSAGE('Address: '& CLIP(PersonGrp.Addresses.City) &', '& CLIP(PersonGrp.Addresses.Street) &', '& AddressQ.House)
  END
  LOOP qIndex = 1 TO RECORDS(PersonGrp.Phones)
    GET(PersonGrp.Phones, qIndex)
    MESSAGE('Phone: '& PersonGrp.Phones.Phone)
  END
  
     MESSAGE('Done')
  end
Возникунт вопросы или потребуются пояснения - непременно спрашивайте ! :)

cJSON: Метод ToGroup() и списки

Добавлено: 09 Октябрь 2024, 8:25
Игорь Столяров
Добрый день !

Если позволите - небольшое дополнение.
В предыдущем примере хорошо было бы ещё обрабатывать особое значение для опции "Instance":0

Это позволит:
1. Обозначить список, для которого нужно сохранить указатель, но не нужно загружать в ToGroup();
2. Сохранять значения других установленных указателей внутри GROUP, например &Group, &String и т.д.
3. И даже сохранять значение полей, которые не нужно обрабатывать внутри ToGroup() !
(это следует из самой красивой идеи ANY полей - почему бы не сделать в CJSON из этого классную фишку ?)

К сожалению, мне неизвестен способ, как можно определить, что поле внутри Group - это указатель.
Поэтому должен быть механизм позволяющий как-то управлять этим вручную - код ведь не сложный.
Потому что обращение к ЛЮБОМУ "очищенному" Clear() указателю - это вылет с GPF. :(

Спасибо за прочтение ! :)

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 17:54
Дед Пахом
Ну нет так нет.

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 18:03
Игорь Столяров
Таки возникли непреодолимые проблемы с прочтением моего примера ?
Или Вы хотите, что бы я вносил изменения для Вас в сам класс ? ;)

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 18:24
Дед Пахом
Для меня?

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 18:37
Игорь Столяров
Я хотел донести до Вас вопросы, которые возникают у меня при просмотре сделанных
Вами примеров c демонстрацией возможностей класса сJSON (см. первое сообщение).

И прошу Вас рассмотреть предлагаемые мною решения этих вопросов.
Если Вы считаете, что с примером всё хорошо - просто скажите и проехали. :)

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 19:06
Дед Пахом
Да рассмотрел я ваши примеры.
Код сохранения значений не рабочий хотя бы для случая вложенных массивов групп. Только не надо говорить, что в таких массивах никто не будет хранить ссылки на очереди.
Игорь Столяров писал(а): 08 Октябрь 2024, 13:57 Хотя кого я пытаюсь обмануть, здесь работы на 15 минут даже для меня ...
...
(*) - Маленькое допущение: что бы не замыливать идею - я не буду копировать сюда код распарса Options.
Если бы вы потратили 16 минут, то нашли бы метод ToGroup, в котором уже есть распарсенные опции, а не первый попавшийся. Плюс -в вашем варианте не чистятся ни очереди, ни таблицы.

А идеи я и сам могу генерировать.

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 19:42
Игорь Столяров
Дед Пахом писал(а): 10 Октябрь 2024, 19:06 хотя бы для случая вложенных массивов групп
Конечно решение должно быть общим.
Но если будет GROUP,DIM(X) с вложенным списком - Вы не сможете задать для этих списков
опцию "Insatance", т.к. имя списка будет одинаковое в каждом элементе массива. Извините. ;)
Дед Пахом писал(а): 10 Октябрь 2024, 19:06 в котором уже есть распарсенные опции, а не первый попавшийся
Методов ToGroup() стало много и разных, но под одним именем.
Я разбираюсь с ними по INС файлу, мог что-то упустить.
Возможно если бы была сводная таблица, как для OPTIONS - пользоваться ими было бы проще.
Дед Пахом писал(а): 10 Октябрь 2024, 19:06 А идеи я и сам могу генерировать.
Я не генерю идеи. Идеи - это что-то новое.
Ранее я рассказывал о вопросах, которые не мог решить существующими методами. Вы помогали.
Конкретно в данной теме я обращаю внимание на проблему с потерей указателей вложенных списков.
Причём проблема демонстрируется на штатном примере. Вот и всё и не более того ... :)

cJSON: Метод ToGroup() и списки

Добавлено: 10 Октябрь 2024, 20:25
Дед Пахом
Спасибо за сигнал, пример исправлю.