Имя: Пароль:
1C
1С v8
не могу прочитать json :(
,
0 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");
        КонецПопытки;
1 I_learn_1c
 
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(тЧтение);
2 palsergeich
 
13.05.20
23:10
(1) проверь то что возвращает сервер валидатором/эдитором, может там не каннонический json.
Например для bulk операций в некоторых системах приходит не json а куча json разделенных символами ПС
https://jsoneditoronline.org/ я этим пользуюсь
3 рикардо милос
 
13.05.20
23:15
Параметры:
<ЧтениеJSON> (обязательный)
Тип: ЧтениеJSON.
Объект чтения JSON.
<ПрочитатьВСоответствие> (необязательный)
Тип: Булево.
Если установлено Истина, чтение объекта JSON будет выполнено в Соответствие.
Если установлено Ложь, объекты будут считываться в объект типа Структура.

вот этот параметр ПрочитатьВСоответствие=Истина
4 palsergeich
 
13.05.20
23:22
(3) чтение в соответствие выручки только тогда когда ключи не могут быть ключами структуры (точка в имени) свойства наприиер и ещё какой то экзотический случай, но там другая ошибка вроде, не про контекст.
5 palsergeich
 
13.05.20
23:23
Я бы таки начал с проверки json на валидность и отсутствие недопустимых символов
6 Asmody
 
13.05.20
23:45
И что показывает отладчик после
СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку();
?
7 Asmody
 
13.05.20
23:46
(5) я бы таки начал с проверки ответа сервера
9 I_learn_1c
 
14.05.20
00:03
(2) https://jsoneditoronline.org/  дерево строит, вроде нормально все
10 Turku
 
14.05.20
00:08
Параметры:
<ЧтениеJSON> (обязательный)
Тип: ЧтениеJSON.
Объект чтения JSON.
<ПрочитатьВСоответствие> (необязательный)
Тип: Булево.
Если установлено Истина, чтение объекта JSON будет выполнено в Соответствие.
Если установлено Ложь, объекты будут считываться в объект типа Структура.
Примечание. При десериализации объектов JSON в структуру необходимо помнить о требованиях к ключам структуры. Если при десериализации объекта будет найдено имя свойства, недопустимое для ключа структуры, то будет вызвано исключение.
Значение по умолчанию: Ложь.

Надо поправить на РезультатСоответствие = ПрочитатьJSON(ЧтениеJSON,Истина);
11 I_learn_1c
 
14.05.20
00:11
(10) не помогает, все равно ошибка про контекст
12 NecroDog
 
14.05.20
00:15
Полное описание ошибки есть? Ошибка метода контекста обычно сопровождается каким-нибудь комментарием.
13 I_learn_1c
 
14.05.20
00:23
(12) неа... все что есть↓

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

Попытка
            РезультатСоответствие = ПрочитатьJSON(ЧтениеJSON, Истина);
        Исключение
            Сообщить("1");
        КонецПопытки;


https://yadi.sk/i/jMGpj7l-Mm8SCg
14 NecroDog
 
14.05.20
00:27
Вызовите метод ПрочитатьJSON вне попытки или в Сообщить() передайте ОписаниеОшибки(). В отладке полное описание ошибки не увидеть.
15 I_learn_1c
 
14.05.20
00:33
(14) ОписаниеОшибки при попадании в исключение в предприятии вывело
{ОбщийМодуль.D3_ИнтеграцияБитрикс.Модуль(44)}: Ошибка при вызове метода контекста (ПрочитатьJSON): Недопустимое состояние потока записи JSON
16 I_learn_1c
 
14.05.20
00:36
(15)уффф... это парсить вручную выходит нужно такое?
17 Garykom
 
гуру
14.05.20
00:37
Пиши HTTPОтвет в файл и читай из файла.
18 Garykom
 
гуру
14.05.20
00:39
(17)+ Два варианта или в строку все не влезло или не валидный json с точки зрения 1С.
Попробуй как в файлу сохранишь поизвращаться с ним, убрать разные левости (типа "\/" и прочего) и выяснить на чем падает.
19 Garykom
 
гуру
14.05.20
00:45
(17)+ Кодировку проверить, может есть некорректные символы на которые валидаторы плюют а 1С падает
20 I_learn_1c
 
14.05.20
00:46
(17) что-то туплю.. а как записать HTTPОтвет в файл?

СтрокаJSON = HTTPОтвет.ПолучитьТелоКакСтроку();
        
        ИмяВремФайла = ПолучитьИмяВременногоФайла("json");
        
        мЗапись = Новый ЗаписьJSON;
        мЗапись.ОткрытьФайл(ИмяВремФайла);
        //?????? что тут
        мЗапись.Закрыть();
21 Garykom
 
гуру
14.05.20
00:56
(20)
ФайлРезультат = ПолучитьИмяВременногоФайла();
затем в СП HTTPСоединение.ОтправитьДляОбработки смотри параметры
22 Garykom
 
гуру
14.05.20
00:59
ФайлРезультат = ПолучитьИмяВременногоФайла();
HTTPОтвет = Соединение.ОтправитьДляОбработки(ЗапросHTTP, ФайлРезультат);
23 I_learn_1c
 
14.05.20
01:04
(21) все равно валится с Недопустимое состояние потока записи JSON... видимо в строке серьезные косяки для 1с

ИмяВремФайла = ПолучитьИмяВременногоФайла();
        HTTPОтвет = Соединение.ОтправитьДляОбработки(ЗапросHTTP,ИмяВремФайла);
        
        //Разбираем ответ        
        тЧтение = Новый ЧтениеJSON;    
        тЧтение.ОткрытьФайл(ИмяВремФайла);
        
        Попытка
            РезультатСоответствие = ПрочитатьJSON(тЧтение, Истина);
        Исключение
            Сообщить(ОписаниеОшибки());
        КонецПопытки;
24 Garykom
 
гуру
14.05.20
01:08
(23) Выложи этот ИмяВремФайла куда то и сам его проверь глазками.
25 Garykom
 
гуру
14.05.20
01:08
(24) *сама
26 Garykom
 
гуру
14.05.20
01:11
27 lodger
 
14.05.20
01:14
(23) это не косяки серьезные, а вариативность JSON не позволяет парсить всё что угодно в полностью автоматическом режиме
читайте https://wonderland.v8.1c.ru/blog/sredstva-raboty-s-json/
хотя бы заголовок "Сериализация типа Дата".
а еще есть педали "Функции преобразования и восстановления".
28 Garykom
 
гуру
14.05.20
01:14
"link":"\/company\/personal\/user\/50\/",

Вот тут лишнее экранирование, только обратный слеш обязательно
"\\" - надо
"/" - можно без экранирование через "\"
29 I_learn_1c
 
14.05.20
01:26
(28) а насчет дат заморачиваться или их должно бы прочитать?
30 Asmody
 
14.05.20
01:27
(8) там написано было почему закрыли
31 Garykom
 
гуру
14.05.20
01:28
(29) Возьми эти строковые даты, вставь в пустой json и попробуй парсятся ли в 1С.
И аналогично со всеми подозрительными
32 vde69
 
14.05.20
07:58
сейчас много работаю с json но не в 1с, основных причин сабжа всего 3

1. не сериализуемый объект
2. не поддерживаемый уровень вложености
3. запрещенные или не поддерживаемые символы

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

1. общая проверка (помогает найти нестандартные символы и объекты)
делаем двойное преобразование в каком онлайн сервисе декоде+обратное кодирование, потом сравниваем строки
2. дробим на куски по уровням вложености и пробуем загрузить в 1с кусочки
33 Василий Алибабаевич
 
14.05.20
08:15
(32) Другое дело. Все сразу стало понятно...)))
Обычно в дешевых американских фильмах вместо вот этого :
"1. не сериализуемый объект
2. не поддерживаемый уровень вложености
3. запрещенные или не поддерживаемые символы"
говорят - "что-то пошло не так".
Результат и одного и другого одинаков.
34 I_learn_1c
 
14.05.20
09:44
(28) какая-то странная фигня происходит..

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

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

                Попытка
            РезультатСоответствие = ПрочитатьJSON(тЧтение,Истина);
            Сообщить("5 все ок");
            Сообщить("5");
        Исключение
            Сообщить("1 "+ОписаниеОшибки());
        КонецПопытки;
35 I_learn_1c
 
14.05.20
09:46
(34) с ошибкой "недопустимое состояние потока записи json"
36 dezss
 
14.05.20
09:55
Сделай уже Сообщить(СтрокаJSON)
И кидай что получилось сюда.
Увидим что не так.
37 Мимохожий Однако
 
14.05.20
09:56
Убери из файла ответа /
38 RomanYS
 
14.05.20
09:57
(34) Убери ПрочитатьJSON из табло отладчика. Ошибка вероятно при повторном вызове.
39 trad
 
14.05.20
09:57
(36) нет, это слишком просто
40 FormatC
 
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, "Массив");
        
        Результат.Вставить("Значение", МассивДанных);
        
    КонецЕсли;
        
    Возврат Результат;
    
КонецФункции
41 dezss
 
14.05.20
09:59
(38) Хм..а это идея...вот даже не думал, что кто-то догадается такое делать.
42 I_learn_1c
 
14.05.20
09:59
(36) там большая строка, прошлую ветку закрыли, за то что вставила
43 arsik
 
гуру
14.05.20
10:01
(42) Сюда закинь https://pastebin.com/
44 trad
 
14.05.20
10:01
(42) облако
45 I_learn_1c
 
14.05.20
10:05
(38) похоже работает... если не ставить точку на самой строке  РезультатСоответствие = ПрочитатьJSON(тЧтение,Истина);


т.е. я потратила день, на то, чтобы это пытаться прочитать без ошибки.. а нужно было ставить в другом месте точку останова..
46 I_learn_1c
 
14.05.20
10:08
(45) точнее точку поставить можно, в табло не надо выводить...  спасибо большое
47 RomanYS
 
14.05.20
10:23
(46) Именно: не надо в табло вызывать методы, которые изменяют контекст
48 dezss
 
14.05.20
10:24
Хм...а фотки в качестве награды не будет?)))