Разбор любого JSON-объекта в соответствующую структуру

Данная публикация предназначена разработчикам 1С, которым приходиться разбирать данные формата JSON. Выложенный пример кода создает объект типа Структура, полностью повторяющий структуру данных формата JSON.

Всех приветствую!

 

Прилагаю несколько функций, которые могут пригодиться другим разработчикам 1С для разбора JSON-объектов и конвертации их в соответствующие структуры:

1. Создаем объект ЧтениеJSON на основе текста объекта:

Функция фПрочитатьJSON(ТекстJSON) Экспорт
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТекстJSON);
Структура = ЗаполнитьСтруктуруИзОтветаJSON(Чтение);
Чтение.Закрыть();
Возврат Структура;
КонецФункции

2. Рекурсивная процедура  для возврата объекта типа Структура

Функция ЗаполнитьСтруктуруИзОтветаJSON(Знач Чтение) Экспорт
Результат = Новый Структура;

ПоследнееИмяРеквизита = Неопределено;

Пока Чтение.Прочитать() Цикл
Тип = Чтение.ТипТекущегоЗначения;
Если Тип = ТипЗначенияJSON.НачалоОбъекта И ПоследнееИмяРеквизита<>Неопределено Тогда
Результат[ПоследнееИмяРеквизита] = ЗаполнитьСтруктуруИзОтветаJSON(Чтение);
ИначеЕсли Тип = ТипЗначенияJSON.КонецОбъекта Тогда
Возврат Результат;
ПоследнееИмяРеквизита = Неопределено;
ИначеЕсли Тип = ТипЗначенияJSON.ИмяСвойства Тогда
Результат.Вставить(Чтение.ТекущееЗначение, Неопределено);
ПоследнееИмяРеквизита = Чтение.ТекущееЗначение;
ИначеЕсли Тип = ТипЗначенияJSON.Булево или Тип = ТипЗначенияJSON.Строка
или Тип = ТипЗначенияJSON.Число или Тип = ТипЗначенияJSON.Null Тогда
Результат[ПоследнееИмяРеквизита] = Чтение.ТекущееЗначение;
ИначеЕсли Тип = ТипЗначенияJSON.НачалоМассива Тогда
Результат[ПоследнееИмяРеквизита] = ЗаполнитьМассивИзОтветаJSON(Чтение);
КонецЕсли;
КонецЦикла;

Возврат Результат;
КонецФункции

3. В случае использования массивов в JSON-объекте используем третью процедуру

Функция ЗаполнитьМассивИзОтветаJSON(Знач Чтение)
Результат = Новый Массив;

Пока Чтение.Прочитать() Цикл
Тип = Чтение.ТипТекущегоЗначения;
Если Тип = ТипЗначенияJSON.НачалоОбъекта Тогда
Результат.Добавить(ЗаполнитьСтруктуруИзОтветаJSON(Чтение));
ИначеЕсли Тип = ТипЗначенияJSON.КонецМассива Тогда
Возврат Результат;
КонецЕсли;
КонецЦикла;

Возврат Результат;
КонецФункции

Вот и все! Всем хорошего времени суток!

13 Comments

  1. dock

    В чем отличие от платформенной ?

    Глобальный контекст (Global context)

    ПрочитатьJSON (ReadJSON)

    Синтаксис:

    ПрочитатьJSON(<ЧтениеJSON>, <ПрочитатьВСоответствие>, <ИменаСвойствСоЗначениямиДата>, <ОжидаемыйФорматДаты>, <ИмяФункцииВосстановления>, <МодульФункцииВосстановления>, <ДополнительныеПараметрыФункцииВосстановления>, <ИменаСвойствДляОбработкиВосстановления>, <МаксимальнаяВложенность>)



    Примечание:


    Массив будет десериализован в массив. Объект JSON будет преобразован в соответствие или структуру (если ключ структуры окажется недопустимым, будет вызвано исключение).

    Для дат действует аналогично методу ПрочитатьДатуJSON.

    Во время выполнения метода может быть вызвана пользовательская функция для восстановления значения — для этого следует использовать параметр <ИмяФункцииВосстановления>. Функция восстановления должна быть описана с директивой &НаСервере или &НаКлиенте. Использование функции вне контекста не допускается.

    Reply
  2. VmvLer

    (1) в том, что автор не читает СП

    Reply
  3. DJDUH

    И, что даже такой кусочек прочтёт?

    {
    «name»: «Иван»,
    «age»: 30,
    «isAdmin»: false,
    «1»: 1,
    «2»: 2,
    «3»: 3
    }
    
    // Или
    
    {
    «ФИО»: «Иванов Иван Иванович»,
    «возраст»: 30,
    «Админ»: false,
    «Контакты»:[
    {       «1»: 1111111,
    «2»: «222-22-22»,
    «3»: 3333333}]
    }
    
    
    

    Показать

    Reply
  4. Eugen-S

    Пример использования «ПрочитатьJSON»:

    ЧтениеJSON = Новый ЧтениеJSON();
    ЧтениеJSON.УстановитьСтроку(ТекстJSON);
    Структура = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    

    Или

    ЧтениеJSON = Новый ЧтениеJSON();
    ЧтениеJSON.ОткрытьФайл(ФайлJSON,»UTF-8″);
    Структура = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    Reply
  5. zavladaev

    (3) Прочитает в соответствие.

    Но такой «кусочек» вышеописанная функция не прочитает.

    Reply
  6. Поручик

    Только я один вытаращил глаза? А как же штатная ПрочитатьJSON? Читает всё, что хочешь, было бы что читать.

    Reply
  7. dock

    (3)

    Не прочитает, само собой.

    Да и опубликованная обработка не прочитает.

    Ошибка будет:

    Недопустимое имя свойства: ‘1’ для чтения JSON в объект Структура

    И это не ошибка JSON — приведенные примеры валидны.

    Это ограничения типа «структура»:

    Структура (Structure)

    Элементы коллекции:

    КлючИЗначение

    Описание:

    Представляет собой коллекцию пар КлючИЗначение. При этом ключ может быть только строковым и должен удовлетворять требованиям, предъявляемым к именованию переменных встроенного языка.
    Reply
  8. Lapitskiy

    Может это для 8.2 ? Там встроенных средств не было..

    Reply
  9. lmnlmn

    (8) Для 8.2 было и есть вот это ))

    Reply
  10. andy_zhav

    Вот такой код разбирает JSON любой вложенности

    Функция РазобратьJSON(Данные)
    Структура = Новый Структура;
    Свойство = Неопределено;
    Значение = Неопределено;
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(Данные);
    Пока ЧтениеJson.Прочитать() Цикл
    ТипJson = ЧтениеJson.ТипТекущегоЗначения;
    Если ТипJSON = ТипЗначенияJSON.Число Или ТипJson = ТипЗначенияJSON.Строка Или
    ТипJson = ТипЗначенияJSON.Булево Или ТипJson = ТипЗначенияJSON.Null Тогда
    Значение = ЧтениеJson.ТекущееЗначение;
    Если Свойство = «GUID» Тогда
    Значение = ПреобразоватьВGUID(Значение);
    КонецЕсли;
    Структура.Вставить(Свойство, Значение);
    //Массив.Добавить(Структура);
    ИначеЕсли ТипJson = ТипЗначенияJSON.ИмяСвойства Тогда
    //Структура.Вставить(Свойство);
    Свойство = ЧтениеJson.ТекущееЗначение;
    КонецЕсли;
    КонецЦикла;
    Возврат Структура;
    КонецФункции
    
    Процедура РазобратьJSONРекурсия(ЧтениеJSON, Дерево)
    
    ИмяСвойства = Неопределено;
    
    Пока ЧтениеJSON.Прочитать() Цикл
    TипJSON = ЧтениеJSON.ТипТекущегоЗначения;
    
    Если TипJSON = ТипЗначенияJSON.НачалоОбъекта
    ИЛИ TипJSON = ТипЗначенияJSON.НачалоМассива Тогда
    НовыйОбъект = ?(TипJSON = ТипЗначенияJSON.НачалоОбъекта, Новый Структура, Новый Массив);
    
    Если ТипЗнч(Дерево) = Тип(«Массив») Тогда
    Дерево.Добавить(НовыйОбъект);
    ИначеЕсли ТипЗнч(Дерево) = Тип(«Структура») И ЗначениеЗаполнено(ИмяСвойства) Тогда
    Дерево.Вставить(ИмяСвойства, НовыйОбъект);
    КонецЕсли;
    
    РазобратьJSONРекурсия(ЧтениеJSON, НовыйОбъект);
    
    Если Дерево = Неопределено Тогда
    Дерево = НовыйОбъект;
    КонецЕсли;
    ИначеЕсли TипJSON = ТипЗначенияJSON.ИмяСвойства Тогда
    ИмяСвойства = ЧтениеJSON.ТекущееЗначение;
    ИначеЕсли TипJSON = ТипЗначенияJSON.Число
    ИЛИ TипJSON = ТипЗначенияJSON.Строка
    ИЛИ TипJSON = ТипЗначенияJSON.Булево
    ИЛИ TипJSON = ТипЗначенияJSON.Null Тогда
    Если ТипЗнч(Дерево) = Тип(«Массив») Тогда
    Дерево.Добавить(ЧтениеJSON.ТекущееЗначение);
    ИначеЕсли ТипЗнч(Дерево) = Тип(«Структура») Тогда
    Дерево.Вставить(ИмяСвойства, ЧтениеJSON.ТекущееЗначение);
    КонецЕсли;
    Иначе
    Возврат;
    КонецЕсли;
    КонецЦикла;
    
    КонецПроцедуры
    

    Показать

    Reply
  11. andy_zhav

    Но имена ключей все-таки лучше с символов начинать

    Reply
  12. capitan

    РаботаВМоделиСервисаБТС.СтруктураИзСтрокиJSON

    Reply
  13. Cifer

    стандартный метод ПрочитатьJSON позволяет прочитать и в структуру и в соответствие.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *