Skip to content

Instantly share code, notes, and snippets.

@bsa7
Last active July 10, 2022 18:12
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save bsa7/9991957 to your computer and use it in GitHub Desktop.
Save bsa7/9991957 to your computer and use it in GitHub Desktop.
1C 7.7 JSON parser 2.0
Процедура СкриптКонтролИнит(scriptCtrl)
scriptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl");
scriptCtrl.Language="jscript";
код = "
|
| function parseJSON(strJSON) {
| var tmpFunc = (new Function('return('+strJSON+');'))();
| return(tmpFunc);
| }
|
| // Получить элемент массива
| function aGet(Array, index) {
| return(Array[index]);
| }
|
| // Получить ключ пары по индексу
| function oKey(Obj, index) {
| var size = 0, key;
| for (key in Obj) {
| if (size == index) break;
| if (Obj.hasOwnProperty(key)) size++;
| }
| return(key);
| }
|
| // Получить значение пары по ключу
| function oValueByKey(Obj, key) {
| return(Obj[key]);
| }
|
| //Получить количество пар в объекте
| Object.size = function(obj) {
| var size = 0, key;
| for (key in obj) {
| if (obj.hasOwnProperty(key)) size++;
| }
| return(size);
| }
|
| //Получить размер объекта (количество пар в нём)
| function oSize(Obj) {
| return(Object.size(Obj));
| }
|
| // Получить тип объекта (number, string, object, array)
| function eType(Element) {
| if (Element instanceof Array) {
| return(""array"");
| } else if (Object.prototype.toString.call(Element) === '[object Array]') {
| return(""array"");
| } else {
| return(typeof(Element));
| }
| }
|";
scriptCtrl.AddCode(код);
КонецПроцедуры
//*******************************************
Функция jsonВСписок(obj)
Если ПустоеЗначение(scriptCtrl)=1 тогда
СкриптКонтролИнит(scriptCtrl);
КонецЕсли;
РезультатРазбора = СоздатьОбъект("СписокЗначений");
//Сообщить(scriptCtrl.run("oSize", obj)); //Размер объекта (количество пар ключ-значение)
//Сообщить(scriptCtrl.run("oKey", obj, 1)); //Ключ пары с номером 1
//Сообщить(scriptCtrl.run("oValueByKey", obj, "id")); //Получить значение объекта по ключу
//Сообщить(scriptCtrl.run("aGet", obj.products, 0).id); //Получить Элемент массива с индексом 0
//Сообщить(scriptCtrl.run("eType", obj.products)); //Получить тип объекта, даже если он - массив
сп = СоздатьОбъект("СписокЗначений");
ТипОбъекта = scriptCtrl.run("eType", obj);
Если ТипОбъекта = "object" Тогда
Для н=0 По scriptCtrl.run("oSize", obj)-1 Цикл
Ключ = scriptCtrl.run("oKey", obj, н);
Значение = scriptCtrl.run("oValueByKey", obj, Ключ);
ТипЗнач = scriptCtrl.run("eType", Значение);
Если Найти("number, string", ТипЗнач) > 0 Тогда
сп.ДобавитьЗначение(Значение, Ключ);
ИначеЕсли Найти("object, array", ТипЗнач) > 0 Тогда
сп.ДобавитьЗначение(jsonВСписок(Значение), Ключ);
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипОбъекта = "array" Тогда
Для н=0 По obj.length-1 Цикл
Значение = scriptCtrl.run("aGet", obj, н);
ТипЗнач = scriptCtrl.run("eType", Значение);
Если Найти("number, string", ТипЗнач) > 0 Тогда
сп.ДобавитьЗначение(Значение, СокрЛП(Строка(н)));
ИначеЕсли Найти("object, array", ТипЗнач) > 0 Тогда
сп.ДобавитьЗначение(jsonВСписок(Значение), СокрЛП(Строка(н)));
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат сп;
КонецФункции //jsonВСписок(obj)
//*********************************************************************************
Функция глРазборJSON(Знач Стр) Экспорт //На входе строка в текущей системной кодировке
Если ПустоеЗначение(scriptCtrl)=1 тогда
СкриптКонтролИнит(scriptCtrl);
КонецЕсли;
Рез = scriptCtrl.run("parseJSON", стр ); //Работает
сп = jsonВСписок(Рез);
Возврат сп;
КонецФункции //глРазборJSON(Знач Стр)
@anten-puzl
Copy link

Пытаюсь обработать ответ с Telegram выдает ошибку Ошибка компиляции Microsoft JScript: Предполагается наличие ')'.

@ermak0ff
Copy link

Падает при большом JSON.

@federicovalenso
Copy link

federicovalenso commented Oct 14, 2019

Для больших json можно поступить так:

function parseJSON(path) {
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    var ts = fso.OpenTextFile(path, 1, true);
    var str = ts.readAll();
    ts.close();
    var json = eval(str);
    return(json);
}

Вместо строки с json передать путь к файлу, в скрипте открыть файл, прочитать его и сделать eval. Пробовал на больших json (порядка 50000 строк), работает мгновенно.

@ermak0ff
Copy link

ermak0ff commented Nov 1, 2019

@federicovalenso, да, спасибо!
единственно что понадобилось обернуть в скобки саму строку:
var json = eval("("+str+")");

@PlagueRus
Copy link

СПАСИБО!

@sergkot
Copy link

sergkot commented Jul 2, 2020

Спасибо, отлично работает, на всякий случай добавлю,а то сам долго не понимал. Кавычки одинарные:
|var json = eval('(' + str + ')');

@bsa7
Copy link
Author

bsa7 commented Jul 2, 2020

Спасибо, отлично работает, на всякий случай добавлю,а то сам долго не понимал. Кавычки одинарные:
|var json = eval('(' + str + ')');

eval - это зло, не такое, как ввп, но всё же не рекомендую.

Кроме того, вообще не рекомендую юзать этот гист, т.к. код медленный. Быстрее будет работать такой код:

Процедура СкриптКонтролИнит(scriptCtrl)
 scriptCtrl =  СоздатьОбъект("MSScriptControl.ScriptControl");
 scriptCtrl.Language="jscript";
 код = "              
  |                    
  | function parseJSON(strJSON) {
  |  return(JSON.parse(strJSON));
  | }
 "
КонецПроцедуры

//*********************************************************************************
Функция разборJSON(Знач Стр) Экспорт //На входе строка в текущей системной кодировке
 Если ПустоеЗначение(scriptCtrl)=1 тогда
  СкриптКонтролИнит(scriptCtrl);
 КонецЕсли;
 Попытка
  т = Создатьобъект("Текст");
  т.ДобавитьСтроку(Стр);
  т.Записать(КаталогИБ()+"err1C.txt");
  Рез = scriptCtrl.run("parseJSON", стр );                               //Работает
 Исключение  
  Сообщить("Ошибка в разборе json: "+Лев(Стр, 220));
  ВызватьИсключение;
 КонецПопытки;
 сп = jsonВСписок(Рез);
 Возврат сп;
КонецФункции //глРазборJSON(Знач Стр)

по моим субъективным оценкам, JSON.parse() работает примерно раз в 5 быстрее.

@sergkot
Copy link

sergkot commented Jul 3, 2020

У меня так не работает.
Ошибка выполнения Microsoft JScript: 'JSON' - определение отсутствует

@vetalkh
Copy link

vetalkh commented Jun 17, 2021

Процедура СкриптКонтролИнит(scriptCtrl)
 scriptCtrl =  СоздатьОбъект("MSScriptControl.ScriptControl");
 scriptCtrl.Language="jscript";
 код = "              
  |                    
  | function parseJSON(strJSON) {
  |  return(JSON.parse(strJSON));
  | }
 "
КонецПроцедуры

Действительно, как сделать доступным класс JSON в Скрипт-шелле?

@PlagueRus
Copy link

Действительно, как сделать доступным класс JSON в Скрипт-шелле?

Возможно, у человека более новая библиотека MSScriptControl.ScriptControl ?
это же JScript и там много чего нет. eval работает, хотя и не безопасно.

@sanekkop
Copy link

sanekkop commented Mar 9, 2022

Добрый день!
Может кто сталкивался с подобной проблемой. При работе с "большими" числовыми значениями, зануляет последние символы.
"{""item"":{""item_id"":1000000000000001}}";
В итоге значение number возвращает "1000000000000000".
Понимаю, что дело в bigint, но как заставить его понимать это?

@bsa7
Copy link
Author

bsa7 commented Mar 9, 2022

@sanekkop - Пробуй в json сохранять эти значения в стоковом типе. А после парсера, уже в твоей обработке, конвертируй обратно в числовой формат 1С.

@sanekkop
Copy link

sanekkop commented Mar 9, 2022

r72cccp - Если бы я формировал сам этот json. Мне его возвращает api. Как это обойти я уже придумал. Я думал может есть способ без "костылей".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment