Report json 1c ошибка

   I_learn_1c

13.05.20 — 23:01

Доброй ночи,

Помогите пожалуйста…..

HTTP ответ нужно прочитать в структуру. Код состояния 200, все норм.

На ПрочитатьJSON(ЧтениеJSON)  Ошибка при вызове метода контекста (ПрочитатьJSON). Что не так не пойму… перечитала синтакс помощник раз 10 уже, даже если пустую строку «{}» дать, то ошибка контекста. Вызывается в общем модуле с галками клиент, сервер, внешнее соединение.

Пишу:

        HTTPОтвет = Соединение.ОтправитьДляОбработки(ЗапросHTTP);

        
        СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку();

            
        //Разбираем ответ        

        ЧтениеJSON = Новый ЧтениеJSON;        

        ЧтениеJSON.УстановитьСтроку(СтрокаJSON);

        
        Попытка

            РезультатСоответствие = ПрочитатьJSON(ЧтениеJSON);

        Исключение

            Сообщить(«1»);

        КонецПопытки;

   I_learn_1c

1 — 13.05.20 — 23:03

(0) если пробую в том же месте простенький пример (ниже), то работает. а как прочитать то что возвращает сервер в СтрокаJSON … не пойму. там много, не стала вставлять сюда

В СтрJSON получается

{

«server»: 10234,

«user»: 3745,

«hash»: «8263ad83ce»

}

Пример кода

ДанныеСтр = Новый Структура(«server,user,hash»,

            10234, 3745, «8263ad83ce»);

            
        мЗапись = Новый ЗаписьJSON;

        мЗапись.УстановитьСтроку();

        ЗаписатьJSON(мЗапись, ДанныеСтр);

        СтрJSON = мЗапись.Закрыть();        

        
        тЧтение = Новый ЧтениеJSON;

        тЧтение.УстановитьСтроку(СтрJSON);

        Структура = ПрочитатьJSON(тЧтение);

   palsergeich

2 — 13.05.20 — 23:10

(1) проверь то что возвращает сервер валидатором/эдитором, может там не каннонический json.

Например для bulk операций в некоторых системах приходит не json а куча json разделенных символами ПС

https://jsoneditoronline.org/ я этим пользуюсь

   рикардо милос

3 — 13.05.20 — 23:15

Параметры:

<ЧтениеJSON> (обязательный)

Тип: ЧтениеJSON.

Объект чтения JSON.

<ПрочитатьВСоответствие> (необязательный)

Тип: Булево.

Если установлено Истина, чтение объекта JSON будет выполнено в Соответствие.

Если установлено Ложь, объекты будут считываться в объект типа Структура.

вот этот параметр ПрочитатьВСоответствие=Истина

   palsergeich

4 — 13.05.20 — 23:22

(3) чтение в соответствие выручки только тогда когда ключи не могут быть ключами структуры (точка в имени) свойства наприиер и ещё какой то экзотический случай, но там другая ошибка вроде, не про контекст.

   palsergeich

5 — 13.05.20 — 23:23

Я бы таки начал с проверки json на валидность и отсутствие недопустимых символов

   Asmody

6 — 13.05.20 — 23:45

И что показывает отладчик после

СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку();

?

   Asmody

7 — 13.05.20 — 23:46

(5) я бы таки начал с проверки ответа сервера

   I_learn_1c

9 — 14.05.20 — 00:03

(2) https://jsoneditoronline.org/  дерево строит, вроде нормально все

   Turku

10 — 14.05.20 — 00:08

Параметры:

<ЧтениеJSON> (обязательный)

Тип: ЧтениеJSON.

Объект чтения JSON.

<ПрочитатьВСоответствие> (необязательный)

Тип: Булево.

Если установлено Истина, чтение объекта JSON будет выполнено в Соответствие.

Если установлено Ложь, объекты будут считываться в объект типа Структура.

Примечание. При десериализации объектов JSON в структуру необходимо помнить о требованиях к ключам структуры. Если при десериализации объекта будет найдено имя свойства, недопустимое для ключа структуры, то будет вызвано исключение.

Значение по умолчанию: Ложь.

Надо поправить на РезультатСоответствие = ПрочитатьJSON(ЧтениеJSON,Истина);

   I_learn_1c

11 — 14.05.20 — 00:11

(10) не помогает, все равно ошибка про контекст

   NecroDog

12 — 14.05.20 — 00:15

Полное описание ошибки есть? Ошибка метода контекста обычно сопровождается каким-нибудь комментарием.

   I_learn_1c

13 — 14.05.20 — 00:23

(12) неа… все что есть↓

Уходит в исключение вот тут, в исключении ИнформацияОбОшибке() или ОписаниеОшибки() возвращают «», если отладкой открыть  ПрочитатьJSON(ЧтениеJSON, Истина), то видна ошибка, и в РезультатСоответствие будет неопределено в итоге

Попытка

            РезультатСоответствие = ПрочитатьJSON(ЧтениеJSON, Истина);

        Исключение

            Сообщить(«1»);

        КонецПопытки;

https://yadi.sk/i/jMGpj7l-Mm8SCg

   NecroDog

14 — 14.05.20 — 00:27

Вызовите метод ПрочитатьJSON вне попытки или в Сообщить() передайте ОписаниеОшибки(). В отладке полное описание ошибки не увидеть.

   I_learn_1c

15 — 14.05.20 — 00:33

(14) ОписаниеОшибки при попадании в исключение в предприятии вывело

{ОбщийМодуль.D3_ИнтеграцияБитрикс.Модуль(44)}: Ошибка при вызове метода контекста (ПрочитатьJSON): Недопустимое состояние потока записи JSON

   I_learn_1c

16 — 14.05.20 — 00:36

(15)уффф… это парсить вручную выходит нужно такое?

   Garykom

17 — 14.05.20 — 00:37

Пиши HTTPОтвет в файл и читай из файла.

   Garykom

18 — 14.05.20 — 00:39

(17)+ Два варианта или в строку все не влезло или не валидный json с точки зрения 1С.

Попробуй как в файлу сохранишь поизвращаться с ним, убрать разные левости (типа «/» и прочего) и выяснить на чем падает.

   Garykom

19 — 14.05.20 — 00:45

(17)+ Кодировку проверить, может есть некорректные символы на которые валидаторы плюют а 1С падает

   I_learn_1c

20 — 14.05.20 — 00:46

(17) что-то туплю.. а как записать HTTPОтвет в файл?

СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку();

        
        ИмяВремФайла = ПолучитьИмяВременногоФайла(«json»);

        
        мЗапись = Новый ЗаписьJSON;

        мЗапись.ОткрытьФайл(ИмяВремФайла);

        //?????? что тут

        мЗапись.Закрыть();

   Garykom

21 — 14.05.20 — 00:56

(20)

ФайлРезультат = ПолучитьИмяВременногоФайла();

затем в СП HTTPСоединение.ОтправитьДляОбработки смотри параметры

   Garykom

22 — 14.05.20 — 00:59

ФайлРезультат = ПолучитьИмяВременногоФайла();

HTTPОтвет = Соединение.ОтправитьДляОбработки(ЗапросHTTP, ФайлРезультат);

   I_learn_1c

23 — 14.05.20 — 01:04

(21) все равно валится с Недопустимое состояние потока записи JSON… видимо в строке серьезные косяки для 1с

ИмяВремФайла = ПолучитьИмяВременногоФайла();

        HTTPОтвет = Соединение.ОтправитьДляОбработки(ЗапросHTTP,ИмяВремФайла);

        
        //Разбираем ответ        

        тЧтение = Новый ЧтениеJSON;    

        тЧтение.ОткрытьФайл(ИмяВремФайла);

        
        Попытка

            РезультатСоответствие = ПрочитатьJSON(тЧтение, Истина);

        Исключение

            Сообщить(ОписаниеОшибки());

        КонецПопытки;

   Garykom

24 — 14.05.20 — 01:08

(23) Выложи этот ИмяВремФайла куда то и сам его проверь глазками.

   Garykom

25 — 14.05.20 — 01:08

(24) *сама

   Garykom

26 — 14.05.20 — 01:11

   lodger

27 — 14.05.20 — 01:14

(23) это не косяки серьезные, а вариативность JSON не позволяет парсить всё что угодно в полностью автоматическом режиме

читайте https://wonderland.v8.1c.ru/blog/sredstva-raboty-s-json/

хотя бы заголовок «Сериализация типа Дата».

а еще есть педали «Функции преобразования и восстановления».

   Garykom

28 — 14.05.20 — 01:14

«link»:»/company/personal/user/50/»,

Вот тут лишнее экранирование, только обратный слеш обязательно

«\» — надо

«/» — можно без экранирование через «»

   I_learn_1c

29 — 14.05.20 — 01:26

(28) а насчет дат заморачиваться или их должно бы прочитать?

   Asmody

30 — 14.05.20 — 01:27

(8) там написано было почему закрыли

   Garykom

31 — 14.05.20 — 01:28

(29) Возьми эти строковые даты, вставь в пустой json и попробуй парсятся ли в 1С.

И аналогично со всеми подозрительными

   vde69

32 — 14.05.20 — 07:58

сейчас много работаю с json но не в 1с, основных причин сабжа всего 3

1. не сериализуемый объект

2. не поддерживаемый уровень вложености

3. запрещенные или не поддерживаемые символы

искать ошибку надо так

1. общая проверка (помогает найти нестандартные символы и объекты)

делаем двойное преобразование в каком онлайн сервисе декоде+обратное кодирование, потом сравниваем строки

2. дробим на куски по уровням вложености и пробуем загрузить в 1с кусочки

   Василий Алибабаевич

33 — 14.05.20 — 08:15

(32) Другое дело. Все сразу стало понятно…)))

Обычно в дешевых американских фильмах вместо вот этого :

«1. не сериализуемый объект

2. не поддерживаемый уровень вложености

3. запрещенные или не поддерживаемые символы»

говорят — «что-то пошло не так».

Результат и одного и другого одинаков.

   I_learn_1c

34 — 14.05.20 — 09:44

(28) какая-то странная фигня происходит..

в общем если поставить одну точку останова на Сообщить(«5 все ок») или Сообщить(«5») то до нее доходит без ошибок, читает в соответствие, и ссылки со слешами верно читает, только дата в виде строки в итоге «2020-05-14T09:34:23+03:00»

в структуру не читает, т.к. есть такое вот в строке «…»edit.originator»:true,…» ну а в структуре нельзя точку в заголовок, ок, допустим, пусть соответствие.

но если поставить точку останова где-то до попытки и идти пошагово, то вываливается на ПрочитатьJSON в исключение…

                Попытка

            РезультатСоответствие = ПрочитатьJSON(тЧтение,Истина);

            Сообщить(«5 все ок»);

            Сообщить(«5»);

        Исключение

            Сообщить(«1 «+ОписаниеОшибки());

        КонецПопытки;

   I_learn_1c

35 — 14.05.20 — 09:46

(34) с ошибкой «недопустимое состояние потока записи json»

   dezss

36 — 14.05.20 — 09:55

Сделай уже Сообщить(СтрокаJSON)

И кидай что получилось сюда.

Увидим что не так.

   МимохожийОднако

37 — 14.05.20 — 09:56

Убери из файла ответа /

   RomanYS

38 — 14.05.20 — 09:57

(34) Убери ПрочитатьJSON из табло отладчика. Ошибка вероятно при повторном вызове.

   trad

39 — 14.05.20 — 09:57

(36) нет, это слишком просто

   FormatC

40 — 14.05.20 — 09:58

Процедура ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, ТипДанных)

    
    ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));    // удалим открывающий символ структуры(массива)

    
    НомерЗначения = 0;

    
    Пока ТекстJSON <> «» Цикл

        
        ПервыйСимвол = Лев(ТекстJSON, 1);

        Если ПервыйСимвол = «{» Тогда

            // вложенная структура

            Значение = Новый Структура;

            ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, «Структура»);

            
            Если ТипДанных = «Структура» Тогда

                Результат.Вставить(«Значение» + ?(НомерЗначения = 0, «», НомерЗначения), Значение);

                НомерЗначения = НомерЗначения + 1;

            ИначеЕсли ТипДанных = «Массив» Тогда

                Результат.Добавить(Значение);

            КонецЕсли;

        
        ИначеЕсли ПервыйСимвол = «[» Тогда

            // вложенный массив

            Значение = Новый Массив;

            ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, «Массив»);

            
            Если ТипДанных = «Структура» Тогда

                Результат.Вставить(«Значение» + ?(НомерЗначения = 0, «», НомерЗначения), Значение);

                НомерЗначения = НомерЗначения + 1;

            Иначе

                Результат.Добавить(Значение);

            КонецЕсли;

            
        ИначеЕсли ПервыйСимвол = «}» И ТипДанных = «Структура» Тогда

            // структура закончилась

            ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));

            Если Лев(ТекстJSON, 1) = «,» Тогда

                ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));

            КонецЕсли;

            
            Возврат;

            
        ИначеЕсли ПервыйСимвол = «]» И ТипДанных = «Массив» Тогда

            // массив закончился

            ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));

            Если Лев(ТекстJSON, 1) = «,» Тогда

                ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));

            КонецЕсли;

            
            Возврат;

            
        Иначе

            
            Если ТипДанных = «Структура» Тогда

                //ПервыйКавычка = Ложь;

                //Если Лев(ТекстJSON, 1) = «»»» Тогда

                //    ПервыйКавычка = Истина;

                //КонецЕсли;

                
                Поз = Найти(ТекстJSON, «:»);

                Если Поз = 0 Тогда

                    // неверный формат, прервемся

                    Прервать;

                КонецЕсли;

                
                //ПредпоследнийКавычка = Ложь;

                //Если Сред(ТекстJSON, Поз — 1, 1) = «»»» Тогда

                //    ПредпоследнийКавычка = Истина;

                //КонецЕсли;

                
                ИмяЗначения = СокрЛП(Лев(ТекстJSON, Поз — 1));

                ИмяЗначения = СтрЗаменить(ИмяЗначения, «»»», «»);

                
                ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз+1));

                                
                Если Лев(ТекстJSON, 1) = «{» Тогда

                    // значение является структурой

                    Значение = Новый Структура;

                    ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, «Структура»);

                    
                ИначеЕсли Лев(ТекстJSON, 1) = «[» Тогда

                    // значение является массивом

                    Значение = Новый Массив;

                    ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, «Массив»);

                    
                Иначе

                    // обычное значение

                    ПервыйКавычка = Ложь;

                    ПредпоследнийКавычка = Ложь;

                    Поз = 0;

                    Для Сч = 1 По СтрДлина(ТекстJSON) Цикл

                        Символ = Сред(ТекстJSON, Сч, 1);

                        
                        Если Символ = «»»» Тогда

                            Если ПервыйКавычка Тогда

                                ПредпоследнийКавычка = Истина;

                            Иначе

                                ПервыйКавычка = Истина;

                            КонецЕсли;                            

                        КонецЕсли;

                        
                        Если (Символ = «,» И ((ПервыйКавычка И ПредпоследнийКавычка) Или (Не ПервыйКавычка И Не ПредпоследнийКавычка))) ИЛИ Символ = «]» ИЛИ Символ = «}» Тогда

                            Поз = Сч;

                            Прервать;

                        КонецЕсли;

                    КонецЦикла;

                    
                    //ПредпоследнийКавычка = Ложь;

                    //Если Сред(ТекстJSON, Поз — 1, 1) = «»»» Тогда

                    //    ПредпоследнийКавычка = Истина;

                    //КонецЕсли;

                    
                    Если Поз = 0 Тогда

                        Значение = ТекстJSON;

                        ТекстJSON = «»;

                        
                    Иначе

                        Значение = Лев(ТекстJSON, Поз — 1);

                        Значение = СтрЗаменить(Значение, «»»», «»);

                        ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = «,», 1, 0)));                        

                    КонецЕсли;

                    
                    Значение = СокрЛП(Значение);

                    
                КонецЕсли;

                
                Попытка

                Результат.Вставить(ИмяЗначения, Значение);

            Исключение

            Конецпопытки;

            
            ИначеЕсли ТипДанных = «Массив» Тогда

                
                // обычное значение

                Поз = 0;

                Для Сч = 1 По СтрДлина(ТекстJSON) Цикл

                    Символ = Сред(ТекстJSON, Сч, 1);

                    Если Символ = «,» ИЛИ Символ = «]» ИЛИ Символ = «}» Тогда

                        Поз = Сч;

                        Прервать;

                    КонецЕсли;

                КонецЦикла;

                
                //ПредпоследнийКавычка = Ложь;

                //Если Сред(ТекстJSON, Поз — 1, 1) = «»»» Тогда

                //    ПредпоследнийКавычка = Истина;

                //КонецЕсли;

                
                Если Поз = 0 Тогда

                    Значение = ТекстJSON;

                    ТекстJSON = «»;

                    
                Иначе

                    Значение = Лев(ТекстJSON, Поз — 1);

                    Значение = СтрЗаменить(Значение, «»»», «»);

                    ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = «,», 1, 0)));

                    
                КонецЕсли;

                
                Значение = СокрЛП(Значение);

                
                Результат.Добавить(Значение);

                
            КонецЕсли;

                
            
        КонецЕсли;

        
    КонецЦикла;

    
КонецПроцедуры

Функция ЗаполнитьСтруктуруИзОтветаJSON(Знач ТекстJSON) Экспорт

    
    Результат = Новый Структура;

    
    ТекстJSON = СтрЗаменить(ТекстJSON, «»»», «»»»);    // заменим последовательность » на »

    ТекстJSON = СтрЗаменить(ТекстJSON, «»»», «»);        // а теперь удалим все кавычки

    
    Если Лев(ТекстJSON, 1) = «{» Тогда

        // начало структуры

        ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, «Структура»);

        
    ИначеЕсли Лев(ТекстJSON, 1) = «[» Тогда

        // начало массива

        МассивДанных = Новый Массив;

        ЗаполнитьДанныеИзОтветаJSON(МассивДанных, ТекстJSON, «Массив»);

        
        Результат.Вставить(«Значение», МассивДанных);

        
    КонецЕсли;

        
    Возврат Результат;

    
КонецФункции

   dezss

41 — 14.05.20 — 09:59

(38) Хм..а это идея…вот даже не думал, что кто-то догадается такое делать.

   I_learn_1c

42 — 14.05.20 — 09:59

(36) там большая строка, прошлую ветку закрыли, за то что вставила

   arsik

43 — 14.05.20 — 10:01

   trad

44 — 14.05.20 — 10:01

(42) облако

   I_learn_1c

45 — 14.05.20 — 10:05

(38) похоже работает… если не ставить точку на самой строке  РезультатСоответствие = ПрочитатьJSON(тЧтение,Истина);

т.е. я потратила день, на то, чтобы это пытаться прочитать без ошибки.. а нужно было ставить в другом месте точку останова..

   I_learn_1c

46 — 14.05.20 — 10:08

(45) точнее точку поставить можно, в табло не надо выводить…  спасибо большое

   RomanYS

47 — 14.05.20 — 10:23

(46) Именно: не надо в табло вызывать методы, которые изменяют контекст

  

dezss

48 — 14.05.20 — 10:24

Хм…а фотки в качестве награды не будет?)))

07.10.2014

Реализовано в версии 8.3.6.1977.

JSON (JavaScript Object Notation) это текстовый формат обмена данными, широко используемый в веб-приложениях. По сравнению с XML он является более лаконичным и занимает меньше места. Кроме этого все браузеры имеют встроенные средства для работы с JSON.

Необходимость работы с этим форматом на уровне платформы обусловлена не только тем, что это «модный современный» формат, который прикладные решения 1С:Предприятия сами по себе могут использовать для интеграции со сторонними приложениями. Другая причина заключается ещё и в том, что JSON активно используется в HTTP интерфейсах. А в 1С:Предприятии как раз есть такие механизмы, в которых хочется использовать этот формат. Это REST интерфейс приложения, автоматически генерируемый платформой, и HTTP-сервисы, которые вы можете создавать самостоятельно.

Мы видим несколько основных сценариев использования JSON.

Во-первых, это интеграция с внешними системами через их HTTP интерфейсы: Google Calendar, Salesforce.com, REST интерфейс 1С:Предприятия, SharePoint и т.д.

Во-вторых, это организация собственного HTTP интерфейса прикладного решения.

В-третьих, обмен файлами JSON с внешними системами. Формирование конфигурационных, настроечных файлов. Использование их в процедурах обмена данными, например, с интернет-магазинами.

В-четвертых, это использование файлов JSON для обмена данными между разными приложениями 1С:Предприятия.

В платформе мы реализовали несколько слоёв работы с JSON. Самые простые и гибкие — это низкоуровневые средства потоковой записи и чтения. Более высокоуровневые и не такие универсальные — средства сериализации в JSON примитивных типов и коллекций 1С:Предприятия.

Потоковое чтение и запись JSON

Объекты потоковой работы — это общие объекты ЧтениеJSON и ЗаписьJSON. Они последовательно читают JSON из файла или строки, или последовательно записывают JSON в файл или строку. Таким образом, чтение и запись JSON происходят без формирования всего документа в памяти.

В качестве иллюстрации потокового чтения JSON можно привести следующий пример:

При записи JSON вы самостоятельно формируете его структуру. Чтобы «подстраховать» вас от ошибок, объект ЗаписьJSON автоматически проверяет правильность записываемой структуры. Для увеличения скорости работы эту проверку можно отключить. В примере ниже это строка:

Также при записи вы можете управлять некоторыми параметрами формируемого текста, например использованием двойных кавычек, переносом строк, символами отступа и экранированием символов. В примере ниже для форматирования текста используется символ табуляции:

Потоковая запись JSON может выглядеть следующим образом. Записывается массив из четырёх элементов. Три из них примитивного типа, а четвёртый элемент — это объект с двумя свойствами:

Результат такой записи:

{
	"СвойствоТипаМассив": [
		"Значение строка",
		1.2345E1,
		true,
		{
			"СвойствоТипаСтрока": "Значение строка",
			"СвойствоТипаНеопределено": null
		}
	]
}

Сериализация примитивных типов и коллекций в JSON

Вторая группа средств работы с JSON хороша тем, что избавляет вас от рутинной работы по чтению/записи каждого отдельного значения или свойства. При чтении документы JSON отображаются в фиксированный набор типов платформы: Строка, Число, Булево, Неопределено, Массив, ФиксированныйМассив, Структура, ФиксированнаяСтруктура, Соответствие, Дата. Соответственно, в обратную сторону, композиция объектов этих типов позволяет сформировать в памяти и быстро записать в файл структуру JSON. Таким образом, чтение и запись небольшого объема JSON заранее известной структуры можно производить немногими строчками кода.

Основное назначение этих средств мы видим в обмене информацией с внешними системами, чтении конфигурационных файлов в формате JSON.

Сериализацию вы можете выполнять с помощью методов глобального контекста ПрочитатьJSON() и ЗаписатьJSON(). Они работают в связке с объектами ЧтениеJSON и ЗаписьJSON.

В качестве примера десериализации JSON можно рассмотреть чтение массива из двух объектов:

[
	{
		"имя": "Anton",
		"фамилия": "Иванов",
		"возраст": 25
	},
	{
		"имя": "Ирина",
		"фамилия": "Иванова",
		"возраст": 20
	}
]

Код 1С:Предприятия, выполняющий десериализацию, может выглядеть следующим образом:

А пример сериализации (записи) в JSON может выглядеть так:

Результат записи:

{
	"Фамилия": "Иванов",
	"Имя": "Иван",
	"Отчество": "Иванович",
	"Возраст": 40,
	"Женат": true,
	"Телефоны": [
		"8-999-999-99-90",
		"8-999-999-99-91"
	]
}

Функции преобразования и восстановления при сериализации

Не всегда сериализация может быть выполнена полностью автоматически. В жизни встречаются самые разные ситуации. Поэтому мы добавили возможность использовать «самописную» функцию обработки значений при записи в JSON и при чтении из JSON.

В методе ЗаписатьJSON() она называется Функция преобразования и описывается с помощью трёх параметров:

  • ИмяФункцииПреобразования;
  • МодульФункцииПреобразования;
  • ДополнительныеПараметрыФункцииПреобразования.

В методе ПрочитатьJSON() она называется Функция восстановления и для неё есть аналогичные параметры:

  • ИмяФункцииВосстановления;
  • МодульФункцииВосстановления;
  • ДополнительныеПараметрыФункцииВосстановления.

При записи в JSON эта функция полезна потому, что позволяет самостоятельно преобразовать в JSON те типы, которые не подлежат автоматическому преобразованию. Или даже совсем отказаться от их сериализации.

Например, так оказалось, что в записываемой структуре одно из значений — это ссылка на элемент справочника ПодразделенияОрганизаций. Такое значение (ссылка на объект 1С:Предприятия) не может быть автоматически сериализовано средствами платформы. Тогда, используя функцию преобразования, мы можем получить для этого значения его строковое представление в удобном виде. Например, в виде строки «ИП Петров: Отдел рекламы».

Результат выполнения примера:

{
	"Фамилия": "Иванов",
	"Имя": "Иван",
	"Отчество": "Иванович",
	"Подразделение": "ИП Петров: Отдел рекламы",
	"Телефоны": [
		"8-999-999-99-90",
		"8-999-999-99-91"
	]
}

При чтении из JSON функция восстановления может использоваться для того, чтобы преобразовать данные JSON в типы 1С, которые не могут являться результатом автоматического преобразования, или для того, чтобы самостоятельно (не автоматически) преобразовать даты JSON в даты 1С:Предприятия.

Сериализация типа Дата

Данные типа Дата сериализуются в JSON автоматически, а вот обратное преобразование (десериализация) может быть выполнено не всегда. JSON не содержит типа Дата, значения даты представляются в нём строкой. Конечно, существуют некоторые форматы представления дат, но вообще говоря, внешний вид такой строки может быть самым разнообразным.

Для сериализации типа Дата в JSON у метода ЗаписатьJSON() вы можете использовать параметр НастройкиСериализации. Это объект встроенного языка, который позволяет указать, в каком варианте будет записана дата (UTC, локальная дата или локальная дата со смещением) и в каком формате (ISO, JavaScript или Microsoft).

Код 1С:Предприятия:

Текст JSON:

[
	{
		"Фамилия": "Иванов",
		"ДатаРождения": "1987-05-14T00:00:00"
	},
	{
		"Фамилия": "Петров",
		"ДатаРождения": "1993-11-21T00:00:00"
	}
]

При чтении даты из JSON всё обстоит сложнее. В параметре ИменаСвойствСоЗначениямиДата вы можете перечислить те свойства JSON, значения которых нужно преобразовать в дату 1С:Предприятия (тип Дата). А в параметре ОжидаемыйФорматДаты вам нужно указать, в каком формате эти данные содержатся в JSON (ISO, JavaScript или Microsoft).

Текст JSON:

[
	{
		"Фамилия": "Иванов",
		"ДатаРождения": "1987-05-14T00:00:00"
	},
	{
		"Фамилия": "Петров",
		"ДатаРождения": "1993-11-21T00:00:00"
	}
]

Код 1С:Предприятия:

Однако если окажется, что в какой-то момент формат данных JSON не совпадает с ожидаемым форматом, будет вызвано исключение.

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

Использование JSON в HTTP интерфейсах приложений

Автоматически генерируемый REST интерфейс прикладных решений

При обращении к REST интерфейсу прикладного решения вы можете получать ответ в формате JSON. Для этого в адресной строке вам нужно указать параметр $format=json. Либо указать MIME тип «application/json» в заголовке Accept HTTP запроса. Например:

Запрос:

GET /TestInfobase/odata/standard.odata/СправочникДляТестов?$format=json HTTP/1.1
MaxDataServiceVersion: 3.0;NetFx
Accept: application/json
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services

Ответ:

HTTP/1.1 200 OK
Content-Length: 9429
Content-Type: application/json;charset=utf-8
Server: Microsoft-IIS/7.5
DataServiceVersion: 3.0
X-Powered-By: ASP.NET
Date: Mon, 12 Aug 2013 09:44:07 GMT
    
{
"odata.metadata":"http://host/svc/$metadata#СправочникДляТестов",
"value":[
{
	"Ref_Key":guid'cc6a7df3-8cfe-11dc-8ca0-000d8843cd1b',
	"DataVersion":"AAAAAQAAAAE",	
	"DeletionMark":false,
	"Parent_Key":guid'bbb079ae-8c51-11db-a9b0-00055d49b45e',
	"IsFolder":false,
	"Code":000000025,
	"Description":"Пинетки",
	"Поставщик_Key":guid'd1cb82a7-8e8b-11db-a9b0-00055d49b45e',
	"Поставщик@navigationLinkUrl":"СправочникДляТестов(guid'cc6a7df3-8cfe-11dc-8ca0-000d8843cd1b')/Поставщик",
	"РеквизитХранилище_Type": "image/jpeg",
	"РеквизитХранилище_Base64Data@mediaReadLink": "Catalog_ДемоСправочник(guid'cf2b1a24-1b96-11e3-8f11-5404a6a68c42')/РеквизитХранилище_Base64Data",
	"РеквизитХранилище_Base64Data": <строка с закодированными данными>
	…
},
{…},
{…}
]
}

Вы можете управлять объёмом передаваемой информации за счёт изменения детальности представления метаданных в выгрузке. Существуют три уровня: Nometadata, Minimalmetadata и Fullmetadata. По-умолчанию (на примере вверху) используется средний уровень — Minimalmetadata. На уровне Nometadata объём передаваемой информации минимальный, а на уровне Fullmetadata — максимальный. Однако при этом нужно понимать, что сокращение объёма передаваемой информации приводит к более интенсивным вычислениям на клиенте. И наоборот, когда вся информация включается в выгрузку, объём вычислений на клиенте будет минимальным.

Детальность представления метаданных вы можете указать, например, в адресной строке.

Сведения о метаданных не передаются:

GET /TestInfobase/odata/standard.odata/СправочникДляТестов/?$format=application/json;odata= minimalmetadata

Вся информация о метаданных включается в выгрузку:

GET /TestInfobase/odata/standard.odata/СправочникДляТестов/?$format=application/json;odata=fullmetadata

HTTP-сервисы прикладного решения

HTTP-сервисы, реализованные в прикладном решении, также могут возвращать ответ в формате JSON. Для этого вам проще всего сформировать тело ответа в JSON, получить его как строку, а затем установить из этой строки тело HTTP ответа сервиса. При этом желательно указать, что BOM (Byte Order Mark, метка порядка байтов) использоваться не должна.

Последний параметр (ИспользованиеByteOrderMark.НеИспользовать) вы можете и не указывать, если режим совместимости конфигурации не установлен, или он больше чем Версия8_3_5. Потому что в этом случае BOM автоматически будет использоваться только для кодировок UTF-16 и UTF-32, а для UTF-8, UTF-16LE/UTF-16BE, UTF-32LE/UTF-32BE и других она использоваться не будет.

Взаимодействие со сторонними HTTP сервисами

При взаимодействии со сторонними HTTP интерфейсами у вас также может возникнуть необходимость формирования запросов к ним в формате JSON. В этом случае алгоритм ваших действий будет аналогичным. Формируете тело запроса в JSON. Получаете тело в виде строки. Из этой строки устанавливаете тело HTTP запроса. BOM не используете.

Дальнейшее развитие

Мы думаем над тем, чтобы предоставить вам возможность сериализации в JSON прикладных типов 1С:Предприятия: ссылок, объектов, наборов записей и т.д. Поэтому есть вероятность появления ещё одного, третьего уровня средств работы с JSON. Этот уровень позволит вам преобразовывать в JSON любые типы 1С:Предприятия, для которых поддерживается XDTO-сериализация в XML.

Теги:
JSON 
8.3.6 
разработка 

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account

Closed

PerlAmutor opened this issue

Feb 8, 2023

· 1 comment

Labels

отклонено

Изменение программы не планируется

проблема

Неожиданное или неудобное поведение программы

Comments

@PerlAmutor

2023-02-08.20-28-03.mp4

Информация для технической поддержки

Платформа: 8.3.20.1996
Режим БД: файловый
Конфигурация. Название: 1С:ERP Управление предприятием 2 (2.5.8.369)
Конфигурация. Основной режим запуска: Управляемое приложение
Конфигурация. Вариант встроенного языка: Русский
Конфигурация. Режим управления блокировкой данных: Управляемый
Конфигурация. Режим совместимости: Версия8_3_17
Конфигурация. Режим использования синхронных вызовов: Использовать
Конфигурация. Версия БСП: 301
Инструменты разработчика. Версия: Портативный 6.63.1p
Инструменты разработчика. Инструмент: Таблица значений
Инструменты разработчика. Перехват клавиатурного ввода: Да
Инструменты разработчика. Объекты на сервере: Да
Инструменты разработчика. Серверный модуль: Да
Клиент. Приложение: Обычное приложение 64б
Клиент. Проверка модальных вызовов: Да
Клиент. Язык интерфейса конфигурации: ru
Клиент. Язык интерфейса системы: ru
Клиент. Отладка разрешена: Да
Клиент. Постоянный кэш метаданных: Да
Клиент. ОС: Майкрософт Windows 10 Pro 64-разрядная Русский
Клиент. ОС от имени администратора: Нет
Клиент. ОС Текущая кодовая страница: 866
Клиент. ОС выполнение BAT: Да

Воспроизведение проблемы

  1. Открыл Консоль запросов
  2. Выполнил запрос:
ВЫБРАТЬ ПЕРВЫЕ 2
	Т.Ссылка КАК Поле1
ИЗ
	Документ.АвансовыйОтчет КАК Т
  1. Выгрузил в Таблицу Значений
  2. Вызвал команду «В строку JSON»
  3. Получил ошибку:
Ошибка при вызове метода контекста (ЗаписатьJSON)
{(1)}:ЗаписатьJSON(ЗаписьJSON, Объект)
{ВнешняяОбработка.ирОбщий.МодульОбъекта(16317)}:	Выполнить("ЗаписатьJSON(ЗаписьJSON, Объект)");
{ВнешняяОбработка.ирПлатформа.Форма.ТаблицаЗначений.Форма(1256)}:	Результат = ирОбщий.ОбъектВСтрокуJSONЛкс(Массив, Истина);
по причине:
Передано значение недопустимого типа

@tormozit

Исправлю подсказку кнопки на «в строку JSON через массив структур. Допустимы только значения примитивных типов.»

Labels

отклонено

Изменение программы не планируется

проблема

Неожиданное или неудобное поведение программы

2 participants

@tormozit

@PerlAmutor

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

В этой статье будет рассмотрена работа с JSON в 1С стандартными средствами.

Напомню, что JSON — это популярный текстовый формат обмена данными. Несмотря на свое происхождения от JavaScript, JSON считается независимым форматом и может использоваться с практически любым языком программирования.

JSON — это достаточно лаконичный формат, что выгодно отличает его от того же XML.

Для начала приведу небольшую теоретическую выдержку с портала ИТС.

Формат JSON является универсальным способом представления при обмене данными. Данные в формате JSON представляют собой (в закодированном виде):

  • Объект – неупорядоченное множество пар ключ:значение, заключенный в фигурные скобки ({}). Пары ключ:значение разделяются запятыми (,);
  • Массив – множество значений. Массив заключается в квадратные скобки ([]). Значения разделяются запятыми (,);
  • Значение – может быть строкой, числом, объектом, массивов или литералом true, false, null:
    • Строка – набор символов, заключенный в двойные кавычки («»);
    • Число – сериализуется с разделителем точка (.). Точность числа не ограничена.

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

Для начала рассмотрим запись в JSON. Запишем простую структуру:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

&НаКлиенте

Процедура ЗаписатьВJSON(Команда)

тЗапись = Новый ЗаписьJSON;

тЗапись.ОткрытьФайл(«C:test.json»);

тДанные = Новый Структура;

тДанные.Вставить(«ЧислоJSON», 100);

тДанные.Вставить(«СтрокаJSON», «test»);

тДанные.Вставить(«ДатаJSON», Дата(2016, 1, 15));

тНастройкиСериализации = Новый НастройкиСериализацииJSON;

тНастройкиСериализации.ФорматСериализацииДаты = ФорматДатыJSON.ISO; //»ДатаJSON»: «2016-03-15T14:19:48»

//тНастройкиСериализации.ФорматСериализацииДаты = ФорматДатыJSON.JavaScript; «ДатаJSON»: «new Date(1452805200000)»

//тНастройкиСериализации.ФорматСериализацииДаты = ФорматДатыJSON.Microsoft; «ДатаJSON»: «/Date(1452805200000)/»

//тНастройкиСериализации.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДата; «ДатаJSON»: «2016-01-15T00:00:00»

//тНастройкиСериализации.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДатаСоСмещением; «ДатаJSON»: «2016-01-15T00:00:00+03:00»

тНастройкиСериализации.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.УниверсальнаяДата; //»ДатаJSON»: «2016-01-14T21:00:00Z»

ЗаписатьJSON(тЗапись, тДанные, тНастройкиСериализации);

тЗапись.Закрыть();

КонецПроцедуры

Представление дат определяется двумя свойствами объекта «НастройкиСериализацииJSON» и соответствующими системными перечислениями «ФорматДатыJSON» и «ВариантЗаписиДатыJSON».

При этом формат даты «JavaScript» и «Microsoft» можно указать, только если вариант записи даты — универсальная дата, иначе при записи возникнет ошибка:

Ошибка при записи JSON

Ошибка при записи JSON

Далеко не все типы данных системы 1С являются JSON-сериализуемыми, решить эту проблему можно при помощи т.н. функции преобразования (отмеченной ключевым словом «Экспорт»). При этом формат сериализации нужно будет прописать в ручную, пример:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

&НаКлиенте

Процедура ЗаписатьВJSON(Команда)

тЗапись = Новый ЗаписьJSON;

тЗапись.ОткрытьФайл(«C:test.json»);

тДанные = Новый Структура;

тДанные.Вставить(«ЧислоJSON», 100);

тДанные.Вставить(«СтрокаJSON», «test»);

тДанные.Вставить(«ДатаJSON», Дата(2016, 1, 15));

тДанные.Вставить(«uidJSON», Новый УникальныйИдентификатор);

ЗаписатьJSON(тЗапись, тДанные, Новый НастройкиСериализацииJSON, «ФункцияПреобразования», ЭтотОбъект);

тЗапись.Закрыть();

КонецПроцедуры

&НаКлиенте

Функция ФункцияПреобразования(Свойство, Значение, ДополнительныеПараметры, Отказ) Экспорт

Если ТипЗнч(Значение) = Тип(«УникальныйИдентификатор») Тогда

Возврат Строка(Значение);

КонецЕсли;

Отказ = Истина;

КонецФункции

Часто бывает, что у нас нет готового объекта для записи, а есть некие данные, которые нуждаются в какой-то предварительной обработке (например выборка запроса), чтобы не формировать промежуточный объект, можно воспользоваться потоковой записью:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

&НаКлиенте

Процедура ЗаписатьВJSON(Команда)

тПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Авто, » «, Истина);

тЗапись = Новый ЗаписьJSON;

тЗапись.ПроверятьСтруктуру = Истина;

тЗапись.ОткрытьФайл(«C:test.json», , , тПараметрыJSON);

тЗапись.ЗаписатьНачалоОбъекта();

тЗапись.ЗаписатьИмяСвойства(«ЧислоJSON»);

тЗапись.ЗаписатьЗначение(100);

тЗапись.ЗаписатьИмяСвойства(«СтрокаJSON»);

тЗапись.ЗаписатьЗначение(«test»);

тЗапись.ЗаписатьИмяСвойства(«МассивJSON»);

тЗапись.ЗаписатьНачалоМассива();

тЗапись.ЗаписатьЗначение(1);

тЗапись.ЗаписатьЗначение(2);

тЗапись.ЗаписатьКонецМассива();

тЗапись.ЗаписатьКонецОбъекта();

тЗапись.Закрыть();

КонецПроцедуры

В коде выше используется объект «ПараметрыЗаписиJSON» с помощью которого можно указать вид переноса строк, символ отступа, использование двойных кавычек, а так же необходимость экранирования различных символов.

При формировании документа JSON можно совмещать объектную и потоковую запись.

Теперь перейдем к чтению JSON, самый простой вариант:

&НаКлиенте

Процедура ЧтениеИзJSON(Команда)

тЧтение = Новый ЧтениеJSON;

тЧтение.ОткрытьФайл(«C:test.json»);

тДанные = ПрочитатьJSON(тЧтение, Ложь);

тДатаJSON = ПрочитатьДатуJSON(тДанные.ДатаJSON, ФорматДатыJSON.ISO);

тЧтение.Закрыть();

КонецПроцедуры

Чтение JSON

Чтение JSON

В примере выше отдельно показано преобразование даты JSON в дату 1С.

Также как и для записи, для чтения существует вариант с т.н. функцией восстановления:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

&НаКлиенте

Процедура ЧтениеИзJSON(Команда)

тЧтение = Новый ЧтениеJSON;

тЧтение.ОткрытьФайл(«C:test.json»);

тДанные = ПрочитатьJSON(тЧтение, Ложь, , , «ФункцияВосстановления», ЭтотОбъект);

тЧтение.Закрыть();

КонецПроцедуры

&НаКлиенте

Функция ФункцияВосстановления(Свойство, Значение, ДополнительныеПараметры) Экспорт

Если Свойство = «ДатаJSON»Тогда

Возврат ПрочитатьДатуJSON(Значение, ФорматДатыJSON.ISO);

КонецЕсли;

Если Свойство = «СтрокаJSON» Тогда

Возврат СокрЛП(Значение);

КонецЕсли;

Если Свойство = «uidJSON» Тогда

Возврат Новый УникальныйИдентификатор(Значение);

КонецЕсли;

КонецФункции

Чтение JSON с функцией восстановления

Чтение JSON с функцией восстановления

Результат практически тот же самый, но «ДатаJSON» и «uidJSON» приведены к типам 1С.

Так же как и для записи, для чтения JSON можно применить потоковый вариант — он особенно полезен, когда объем JSON-данных велик (не загружает эти данные в память), а искомое значение находится в начале файла.

Простой вариант потокового чтения выглядит так:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

&НаКлиенте

Процедура ЧтениеИзJSON(Команда)

тЧтение = Новый ЧтениеJSON;

тЧтение.ОткрытьФайл(«C:test.json»);

Пока тЧтение.Прочитать() Цикл

Сообщить(«Тип текущего элемента » + тЧтение.ТипТекущегоЗначения);

Если тЧтение.ТипТекущегоЗначения = ТипЗначенияJSON.ИмяСвойства Тогда

Сообщить(«Имя = » + тЧтение.ТекущееЗначение);

КонецЕсли;

Если тЧтение.ТипТекущегоЗначения = ТипЗначенияJSON.Булево ИЛИ

тЧтение.ТипТекущегоЗначения = ТипЗначенияJSON.Строка ИЛИ

тЧтение.ТипТекущегоЗначения = ТипЗначенияJSON.Число ИЛИ

тЧтение.ТипТекущегоЗначения = ТипЗначенияJSON.Комментарий Тогда

Сообщить(«Значение = » + тЧтение.ТекущееЗначение);

КонецЕсли;

КонецЦикла;

тЧтение.Закрыть();

КонецПроцедуры

На этом все, надеюсь эта статья Вам помогла.

Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Загрузка…

Ошибка «Недопустимое состояние потока записи JSON» 1С 8.3

Указанная в заголовке ошибка возникает, в момент вызова метода ПрочитатьJSON, если ранее параметр типа ЧтениеJSON, был инициализирован пустой строкой.

Вызывающий ошибку код:

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

Работающий код

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

То есть требуется передавать объект заданный фигурными скобками.

Примечание

Отмечу, что функции для работы с JSON появились в платформе 1с 8.3.6, ранее json можно было использовать через функции, которые распространялись в сообществах еще с 7.7 версии.

Реклама — искусство превращения полуправды в полную ложь.

Понравилась статья? Поделить с друзьями:
  • Replace image drum oki ошибка
  • Replace drum cart xerox 3330 ошибка
  • Repetier host ошибка объект не замкнут
  • Repetier host ошибка com порта
  • Repair windowsimage сбой repair windowsimage код ошибки 0x800f0906