Парсинг вложенных групп в cJSON

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
harry
Бывалый
Сообщения: 69
Зарегистрирован: 24 Февраль 2015, 14:16
Поблагодарили: 3 раза

Парсинг вложенных групп в cJSON

Сообщение harry »

Наткнулся на некорректный парсинг при наличии повтояющихся имен полей во вложенных группах

Парсим, например, такой JSON

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

{
			"RecipientReceiptMetadata": {
				"ReceiptStatus": "000",
				"ConfirmationMetadata": {
					"ReceiptStatus": "111",
					"DateTimeTicks": 637852826568038296
				}
			},
			"ConfirmationMetadata": {
				"ReceiptStatus": "222",
				"DateTimeTicks": 637852826113117146
			},
			"AmendmentRequestMetadata": {
				"AmendmentFlags": 3,
				"ReceiptStatus": "333"
			}
}			

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

_DD_ReceiptStatus         Group,Type
ReceiptStatus                      string(40)
                                end

_DD_ConfirmationMetadata        Group(_DD_ReceiptStatus),Type
DateTimeTicks                      string(40)
                                end
_DD_RecipientReceiptMetadata    Group(_DD_ReceiptStatus),Type
ConfirmationMetadata               Group(_DD_ConfirmationMetadata)
                                end

_DD_AmendmentRequestMetadata    Group(_DD_ReceiptStatus),Type
AmendmentFlags                     string(10)
                                end

Document                        Group
RecipientReceiptMetadata           Group(_DD_RecipientReceiptMetadata).
ConfirmationMetadata               Group(_DD_ConfirmationMetadata). 
AmendmentRequestMetadata           Group(_DD_AmendmentRequestMetadata). 
                            end
  Code
  ret# = parser.ToGroup(Document)							
В результате,

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

Document.RecipientReceiptMetadata.ReceiptStatus = '000' !верно
Document.RecipientReceiptMetadata.ConfirmationMetadata.ReceiptStatus = '222' !должно быть '111'
ConfirmationMetadata.ReceiptStatus = '' !должно быть '222'
AmendmentRequestMetadata.ReceiptStatus = '333' !верно
Есть способ решить эту проблему ?
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3144
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 11 раз
Поблагодарили: 32 раза
Контактная информация:

Парсинг вложенных групп в cJSON

Сообщение Дед Пахом »

Не знаю, в одной группе 4 одноимённых поля, трудно определить, к какому полю что из json относится.
**
Переношу тему в форум Библиотеки и шаблоны-cJSON, давайте там новые темы создавать.
С уважением, ДП
harry
Бывалый
Сообщения: 69
Зарегистрирован: 24 Февраль 2015, 14:16
Поблагодарили: 3 раза

Парсинг вложенных групп в cJSON

Сообщение harry »

Видимо, так происходит из-за того , что все элементы группы просматриваются.
В штатном парсере есть код, который в случае не нахождения текущей группы из JSON в структуре группы Clarion , подсчитывает количество элементов в этой группе и пропускает ее. Это решает проблему, но как я понял, этот код создают жуткие тормоза с накопительным эффектом.

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

             !If it is not the name but it is a GROUP then skip all the internal items
             IF ISGROUP(pJSONObject,idx)
                innerGroup &= GETGROUP(pJSONObject, idx,1)
                idx += (SELF.GetGroupNumberOfFields(innerGroup) - 1)
             END
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3144
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 11 раз
Поблагодарили: 32 раза
Контактная информация:

Парсинг вложенных групп в cJSON

Сообщение Дед Пахом »

Я бы предложил такую схему:

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

  jRoot &= jParser.Parse(response)
  IF NOT jRoot &= NULL
    jRoot.ToGroup(MainGroup)
    jRoot.ToGroup('InnerGroup1', InnerGroup1)
    jRoot.ToGroup('InnerGroup2', InnerGroup2)
    
    jRoot.Delete()
  END
С уважением, ДП
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3144
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 11 раз
Поблагодарили: 32 раза
Контактная информация:

Парсинг вложенных групп в cJSON

Сообщение Дед Пахом »

Ну да, вот так работает. Я переименовал имена групп (добавил "Grp" в конец имён), чтобы они НЕ соответствовали именам объектов в json и таким образом не обрабатывались в jRoot.ToGroup(Document).

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

_DD_ReceiptStatus               Group,Type
ReceiptStatus                     string(40)
                                end

_DD_ConfirmationMetadata        Group(_DD_ReceiptStatus),Type
DateTimeTicks                     string(40)
                                end

_DD_RecipientReceiptMetadata    Group(_DD_ReceiptStatus),Type
ConfirmationMetadataGrp           Group(_DD_ConfirmationMetadata)
                                  end
                                END

_DD_AmendmentRequestMetadata    Group(_DD_ReceiptStatus),Type
AmendmentFlags                    string(10)
                                end

Document                        Group
RecipientReceiptMetadataGrp       Group(_DD_RecipientReceiptMetadata).
ConfirmationMetadataGrp           Group(_DD_ConfirmationMetadata).
AmendmentRequestMetadataGrp       Group(_DD_AmendmentRequestMetadata).
ReceiptStatus                     string(40)
                                end

jParser                         cJSONFactory
jRoot                           &cJSON, AUTO
jRecipientReceiptMetadata       &cJSON, AUTO

  CODE
  jRoot &= jParser.Parse(json)
  IF NOT jRoot &= NULL
    !- Читаем корневые данные (вне всех групп)
    jRoot.ToGroup(Document)
    
    !- Читаем группы без вложенных групп
    jRoot.ToGroup('ConfirmationMetadata', Document.ConfirmationMetadataGrp)
    jRoot.ToGroup('AmendmentRequestMetadata', Document.AmendmentRequestMetadataGrp)
    
    !- Читаем группы с вложенными группами
    jRecipientReceiptMetadata &= jRoot.GetObjectItem('RecipientReceiptMetadata')
    IF NOT jRecipientReceiptMetadata &= NULL
      jRecipientReceiptMetadata.ToGroup(Document.RecipientReceiptMetadataGrp)
      jRecipientReceiptMetadata.ToGroup('ConfirmationMetadata', Document.RecipientReceiptMetadataGrp.ConfirmationMetadataGrp)
    END
   
    printd('Document.RecipientReceiptMetadata.ReceiptStatus=%s', Document.RecipientReceiptMetadataGrp.ReceiptStatus)
    printd('Document.RecipientReceiptMetadata.ConfirmationMetadata.ReceiptStatus=%s', Document.RecipientReceiptMetadataGrp.ConfirmationMetadataGrp.ReceiptStatus)
    printd('Document.ConfirmationMetadata.ReceiptStatus=%s', Document.ConfirmationMetadataGrp.ReceiptStatus)
    printd('Document.AmendmentRequestMetadata.ReceiptStatus=%s', Document.AmendmentRequestMetadataGrp.ReceiptStatus)

    jRoot.Delete()
  END
С уважением, ДП
Ответить