// Кэширование загруженных данных, для исключения повторной загрузки
// Соответствие: ресурс трекера - полученные данные 
Перем ЗагруженныеДанные Экспорт;

// Исключаем повторную инициализацию HTTPСоединения
Перем мHTTPСоединение;

// Путь к внешней библиотеке конвертера Teaxtile В HTML
Перем мКонвертерTextileToHTML;

// Реализация прав доступа к некоторым функциям (удаление задач)
Перем мПолныеПрава Экспорт;

////////////////////////////////////////////////////////////////////////////////
// ЭКСПОРТНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ 

// Формирует структуру для передачи сообщений о выполнении запросов между клиентом и сервером
//
Функция СформироватьСтруктуруОтчетаОВыполнении() Экспорт
	Возврат Новый Структура("ЕстьОшибки, ТекстОшибки, КодСостояния", Ложь, "", 0);	
КонецФункции

Функция ПолучитьДанныеРесурсаИзТрекера(Ресурс, ОтчетоВыполнении, Параметры = "") Экспорт
	
	СтруктураЗапроса = Новый Структура("Метод, АдресЗапроса, Параметры", "GET", "/"+Ресурс+".json", Параметры);
	
	Результат = ОтправитьЗапросВтрекер(СтруктураЗапроса, ОтчетоВыполнении);
	
	ЗагруженныеДанные.Вставить(Ресурс, Результат);
	
	Возврат Результат;
КонецФункции

Функция СоздатьЗадачуВТрекере(ОтчетоВыполнении) Экспорт
	
	//Если есть вложения снчала загрузим вложения
	Если Вложения.Количество() <> 0 Тогда
		Для Каждого Вложение Из Вложения Цикл
			Результат = ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("POST", "uploads", Вложение.ПолноеИмяФайла), ОтчетоВыполнении);
			Вложение.Токен = Результат.upload.token;
		КонецЦикла;
	КонецЕсли;
	
	// Подготовить файл к отправке в трекер
	ФайлКОтправке = ПреобразоватьСтруктуруВ_JSON(СформироватьСтруктуруЗадачи(), ОтчетоВыполнении);
	
	Результат = ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("POST", "issues", ФайлКОтправке), ОтчетоВыполнении);
	
	Возврат Результат;
КонецФункции

Функция ОбновитьЗадачуВТрекере(ОтчетоВыполнении) Экспорт
	
	//Если есть вложения снчала загрузим вложения
	Если Вложения.Количество() <> 0 Тогда
		Для Каждого Вложение Из Вложения Цикл
			Если Вложение.Пометка Тогда
				Результат = ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("POST", "uploads", Вложение.ПолноеИмяФайла), ОтчетоВыполнении);
				Вложение.Токен = Результат.upload.token;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	// Подготовить файл к отправке в трекер
	ФайлКОтправке = ПреобразоватьСтруктуруВ_JSON(СформироватьСтруктуруЗадачи(Истина), ОтчетоВыполнении);
	
	Результат = ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("PUT", "issues/"+Формат(ЗадачаНомер, "ЧГ=0"), ФайлКОтправке), ОтчетоВыполнении);
	
	Если ОтчетоВыполнении.ЕстьОшибки Тогда
		Возврат Результат;
	КонецЕсли;
	
	// Зарегестрировать данные о затраченном времени
	Если ЗадачаЗатраченноеВремя <> 0  Тогда
		ФайлКОтправке = ПреобразоватьСтруктуруВ_JSON(СформироватьСтрутуруЗаписиЗатраченногоВремени(), ОтчетоВыполнении);
		
		Результат = ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("POST", "time_entries", ФайлКОтправке), ОтчетоВыполнении);
	КонецЕсли;
	
	Возврат Результат;
КонецФункции

Функция УдалитьЗадачуИзТрекера(НомерЗадачи, ОтчетоВыполнении) Экспорт
	
	//1. получить связанные задачи, если они есть необходимо эти связи удалить
	ДанныеСвязей = ПолучитьДанныеРесурсаИзТрекера("/issues/"+Формат(НомерЗадачи, "ЧГ=0")+"/relations", ОтчетОВыполнении);
	
	Если ДанныеСвязей <> Неопределено Тогда  // Необходимо удалить связи
		Для Каждого Связь Из ДанныеСвязей["relations"] Цикл
			ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("DELETE", "/relations/"+Связь.id), ОтчетоВыполнении);		
			Если ОтчетоВыполнении.ЕстьОшибки Тогда
				Возврат Ложь;		
			КонецЕсли;	
		КонецЦикла;	
	КонецЕсли;
	
	//2. удаление задачи
	ОтправитьЗапросВТрекер(СформироватьСтруктуруЗапросаВТрекер("DELETE", "/issues/"+Формат(НомерЗадачи, "ЧГ=0")), ОтчетоВыполнении);		
	Если ОтчетоВыполнении.ЕстьОшибки Тогда
		Возврат Ложь;		
	КонецЕсли;	
	
	Возврат Истина;
КонецФункции

Функция ЗадачаУжеДобавленаВТрекер(СтруктураДанных, ОтчетоВыполнении) Экспорт
	//Закладка{Реализовать функцию ЗадачаУжеДобавленаВТрекер}
	
	//СтруктураЗапроса = Новый Структура("Метод, АдресЗапроса, ФайлОтвета, Параметры", "GET", "/issues.json");
	//СтруктураЗапроса.ФайлОтвета = ПолучитьИмяВременногоФайла("json");
	//
	//СтруктураЗапроса.Параметры = "";
	//СтруктураЗапроса.Параметры = СтруктураЗапроса.Параметры + "&project_id="+СтруктураДанных.issue.project_id;
	//СтруктураЗапроса.Параметры = СтруктураЗапроса.Параметры + "&subject="+СтруктураДанных.issue.subject;	
	//
	//HTTPОтвет = ОтправитьЗапросВтрекер(СтруктураЗапроса, ОтчетоВыполнении);
	//
	//Результат = ОбработатьРезультатОтвета(HTTPОтвет, ОтчетоВыполнении);
	
	Возврат Неопределено;
КонецФункции

Функция ПолучитьИдентификаторПараметра(ИмяПараметра, Ресурс) Экспорт 
	
	Данные = ЗагруженныеДанные.Получить(Ресурс);
	Если Данные <> Неопределено Тогда
		Для Каждого СтрокаДанные Из Данные[Ресурс] Цикл
			Если СтрокаДанные.Свойство("name") И ИмяПараметра = СтрокаДанные.name Тогда
				Возврат СтрокаДанные.id;
			ИначеЕсли СтрокаДанные.Свойство("user") И ИмяПараметра = СтрокаДанные.user.name Тогда
				Возврат СтрокаДанные.user.id;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат 0;
КонецФункции


// Формирование структур данных для дальнейшей сериализации в JSON и отправке в трекер
//
Функция СформироватьСтруктуруЗадачи(Редактирование=Ложь)
	
	Задача = Новый Структура;
	
	ПоляЗадачи = Новый Структура;
	ПоляЗадачи.Вставить("project_id",             ПолучитьИдентификаторПараметра(ЗадачаПроект, "projects"));
	ПоляЗадачи.Вставить("parent_issue_id",    	  ?(ЗадачаНомерРродительскойЗадачи = 0, Неопределено, ЗадачаНомерРродительскойЗадачи)); 	
	ПоляЗадачи.Вставить("tracker_id",             ПолучитьИдентификаторПараметра(ЗадачаТрекер, "trackers"));
	ПоляЗадачи.Вставить("status_id",              ПолучитьИдентификаторПараметра(ЗадачаСтатус, "issue_statuses"));
	ПоляЗадачи.Вставить("priority_id",            ПолучитьИдентификаторПараметра(ЗадачаПриоритет, "issue_priorities"));
	ПоляЗадачи.Вставить("subject",                ЗадачаТема);
	ПоляЗадачи.Вставить("description",            ЗадачаОписание);
	ПоляЗадачи.Вставить("estimated_hours",        ЗадачаОценкаВремени); 
	ПоляЗадачи.Вставить("start_date",             Формат(ЗадачаНачалоВыполнения, "ДФ=yyyy-MM-dd")); 
	ПоляЗадачи.Вставить("due_date",               Формат(ЗадачаКонецВыполнения, "ДФ=yyyy-MM-dd")); 
	ПоляЗадачи.Вставить("assigned_to_id",         ПолучитьИдентификаторПараметра(ЗадачаИсполнитель, "memberships")); 
	
	Если Редактирование И ЗначениеЗаполнено(ЗадачаПримечание) Тогда
		ПоляЗадачи.Вставить("notes", ЗадачаПримечание); 
	КонецЕсли;
	
	мНаблюдателей = Новый Массив;
	Для Каждого стрНаблюдатель Из Наблюдатели Цикл
		Если стрНаблюдатель.Пометка Тогда
			мНаблюдателей.Добавить(стрНаблюдатель.Идентификатор);
		КонецЕсли;
	КонецЦикла;
	Если мНаблюдателей.Количество() <> 0 Тогда
		ПоляЗадачи.Вставить("watcher_user_ids", мНаблюдателей);
	КонецЕсли;
	
	мНастраиваемыхПолей = Новый Массив;
	Для Каждого Поле Из НастраиваемыеПоля Цикл
		Если Поле.Пометка Тогда
			мНастраиваемыхПолей.Добавить(Новый Структура("id, value", Поле.Идентификатор, Поле.Значение));
		КонецЕсли;
	КонецЦикла;
	Если мНастраиваемыхПолей.Количество() <> 0 Тогда
		ПоляЗадачи.Вставить("custom_fields", мНастраиваемыхПолей);
	КонецЕсли;
	
	//"parent_issue_id" 	// ID of the parent issue 
	//"custom_fields" 		// See Custom fields 
	//"watcher_user_ids" 	// Array of user ids to add as watchers (since 2.3.0)  
	//"is_private"  		// Use true or false to indicate whether the issue is private or not
	//"estimated_hours"  	// Number of hours estimated for issue
	
	Если Вложения.Количество() <> 0 Тогда
		мФайлов = Новый Массив;
		Для Каждого Вложение  Из Вложения Цикл
			Если Не Вложение.Пометка Тогда
				Продолжить;
			КонецЕсли;
			
			Файл = Новый Файл(Вложение.ПолноеИмяФайла);
			MIMEТип = ПолучитьMIMEТип(Файл.Расширение);
			
			Если ЗначениеЗаполнено(MIMEТип) Тогда
				мФайлов.Добавить(Новый Структура("token, filename, content_type", Вложение.Токен, Файл.Имя, MIMEТип));
			КонецЕсли;
		КонецЦикла;
		
		ПоляЗадачи.Вставить("uploads", мФайлов); 
	КонецЕсли;
	//    "uploads": [
	//  {"token": "7167.ed1ccdb093229ca1bd0b043618d88743", "filename": "image.png", "content_type": "image/png"}
	//]

	Задача.Вставить("issue", ПоляЗадачи);
	
	Возврат Задача;
КонецФункции

Функция СформироватьСтрутуруЗаписиЗатраченногоВремени()
	
	ЗаписиВремени = Новый Структура;
	
	Запись = Новый Структура;
	Запись.Вставить("issue_id",       Формат(ЗадачаНомер, "ЧГ=0"));
	//Запись.Вставить("spent_on",       Формат(ЗадачаНомер, "ЧГ=0"));
	Запись.Вставить("hours",          Формат(ЗадачаЗатраченноеВремя, "ЧГ=0"));
	Запись.Вставить("activity_id",    ПолучитьИдентификаторПараметра(ЗадачаДеятельность, "time_entry_activities"));
	
	Если ЗадачаКомментарии <> "" Тогда
		Запись.Вставить("comments", ЗадачаКомментарии); 
	КонецЕсли;

	ЗаписиВремени.Вставить("time_entry", Запись);
	
	Возврат ЗаписиВремени;
КонецФункции



Функция ПолучитьMIMEТип(Расширение)
	//:	Файл = Новый Файл("");
	
	Если Расширение = ".jpg" Или Расширение = ".png" 
		Или Расширение = ".bmp" Или Расширение = ".gif" Или Расширение = ".jpeg" Тогда // image/*
		
		MIMEТип = "image/"+Прав(Расширение, СтрДлина(Расширение)-1);
	ИначеЕсли Расширение = ".txt" Или Расширение = ".css" 
		Или Расширение = ".csv" Или Расширение = ".html" Или Расширение = ".xml" Тогда // text/*
		
		MIMEТип = "text/"+Прав(Расширение, СтрДлина(Расширение)-1);
	Иначе // file/*
		
		MIMEТип = "file/"+Прав(Расширение, СтрДлина(Расширение)-1);
	КонецЕсли;
	
	Возврат MIMEТип;
КонецФункции


Функция СформироватьСтруктуруЗапросаВТрекер(Метод, Ресурс, ФайлКотправке = Неопределено)
	
	СтруктураЗапроса = Новый Структура("Метод, АдресЗапроса, ФайлКОтправке, Параметры", Метод, "/"+Ресурс+".json");
	
	СтруктураЗапроса.ФайлКОтправке = ФайлКотправке;
	Возврат СтруктураЗапроса;

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

Функция ОтправитьЗапросВТрекер(СтруктураЗапроса, ОтчетоВыполнении)
	
	Таймаут = 3;
	
	Если НЕ ЗначениеЗаполнено(APIkey) Тогда
		ОтчетоВыполнении.ЕстьОшибки = Истина;
		ОтчетоВыполнении.ТекстОшибки = "Не указан API key для доступа к трекеру Redmine!";
		Возврат Неопределено;
	КонецЕсли;
	ОбязательныйПараметр = "?key="+APIkey;
	
	Если СтруктураЗапроса.Параметры = Неопределено Тогда
		СтруктураЗапроса.Параметры = "";
	КонецЕсли;
	Если ПределПолучаемыхДанных <> 0 Тогда
		СтруктураЗапроса.Параметры = СтруктураЗапроса.Параметры + "&limit="+ПределПолучаемыхДанных;		// количество получаемых записей (по умолчанию 25) 
	КонецЕсли;
	
	Если мHTTPСоединение = Неопределено Тогда
		мHTTPСоединение = Новый HTTPСоединение(Сервер, Порт, Пользователь, Пароль,, Таймаут);
	КонецЕсли;
	
	Параметры = ОбязательныйПараметр + СтруктураЗапроса.Параметры;
	
	Попытка
		Если СтруктураЗапроса.Метод = "GET" Тогда
			HTTPОтвет = мHTTPСоединение.Получить(Новый HTTPЗапрос(СтруктураЗапроса.АдресЗапроса+Параметры));
		Иначе
			Если Найти(СтруктураЗапроса.АдресЗапроса, "uploads") > 0 Тогда
				Заголовки = Новый Соответствие;
				Заголовки.Вставить("Content-Type", "application/octet-stream");
			Иначе
				Заголовки = Новый Соответствие;
				Заголовки.Вставить("Content-Type", "application/json");
			КонецЕсли;
			
			HTTPЗапрос = Новый HTTPЗапрос(СтруктураЗапроса.АдресЗапроса);
			Если НЕ СтруктураЗапроса.ФайлКОтправке = Неопределено  Тогда
				HTTPЗапрос.УстановитьИмяФайлаТела(СтруктураЗапроса.ФайлКОтправке);
			КонецЕсли;
			HTTPЗапрос.Заголовки = Заголовки;
			
			HTTPОтвет = мHTTPСоединение.ВызватьHTTPМетод(СтруктураЗапроса.Метод, HTTPЗапрос);
		КонецЕсли;
	Исключение
		ОтчетоВыполнении.ЕстьОшибки = Истина;
		ОтчетоВыполнении.ТекстОшибки = "Не удалось соединится с сервером Redmine!" + Символы.ПС +  ОписаниеОшибки();
		Возврат Неопределено;
	КонецПопытки;

	Возврат ОбработатьРезультатОтвета(HTTPОтвет, ОтчетоВыполнении); 
КонецФункции

Функция ОбработатьРезультатОтвета(HTTPОтвет, ОтчетОВыполнении)
	Перем Результат;	
	
	//: HTTPСоединение = Новый HTTPСоединение("", , "", ""); HTTPОтвет = HTTPСоединение.Получить(Новый HTTPЗапрос(""));
	
	Если HTTPОтвет <> Неопределено Тогда
		
		Результат = ПреобразоватьJSON_ВСтруктуру(HTTPОтвет.ПолучитьТелоКакСтроку());
		
		Если HTTPОтвет.КодСостояния = 200 Тогда // Успешнае выполнение запроса
			ОтчетОВыполнении.КодСостояния = HTTPОтвет.КодСостояния; 
			Возврат Результат;
		КонецЕсли;
		
		Если Результат = Неопределено Тогда
			ОтчетоВыполнении.ЕстьОшибки = Истина;
			ОтчетоВыполнении.ТекстОшибки = "Ошибка выполнения запроса. Код состояния:" + HTTPОтвет.КодСостояния;
			ОтчетоВыполнении.ТекстОшибки = ОтчетоВыполнении.ТекстОшибки + Символы.ПС + "Результат ответа сервера неопределен, проверьте настройки!";
			Возврат Неопределено;
		КонецЕсли;

		Если Результат.Свойство("errors") Тогда
			ОтчетоВыполнении.ЕстьОшибки = Истина;
			ОтчетоВыполнении.ТекстОшибки = "Ошибка выполнения запроса. Код состояния:" + HTTPОтвет.КодСостояния;
			Для Каждого Ошибка Из Результат.errors Цикл
				ОтчетоВыполнении.ТекстОшибки = ОтчетоВыполнении.ТекстОшибки + Символы.ПС + Ошибка;
			КонецЦикла;
			Возврат Результат;
		КонецЕсли;
		
		//УдалитьФайлы(HTTPОтвет.ПолучитьИмяФайлаТела());
	КонецЕсли;
	
	Возврат Результат;
КонецФункции



Функция ПреобразоватьСтруктуруВ_JSON(СтруктураДанных, ОтчетОВыполнении)
	
	ФайлКОтправке = ПолучитьИмяВременногоФайла("json");
	
	СтрокаJSON = асЗаписатьJSON(СтруктураДанных, Ложь);
	
	// Запись в Файл необходимоа для удаления управляющего BOM символа, т.к. присутствие такового вызывает исключение в трекере
	ЗТ = Новый ЗаписьТекста(ФайлКОтправке,,, Истина, Символы.ПС); 
	ЗТ.Записать(СтрокаJSON); 
	ЗТ.Закрыть(); 
	
	// 	Для 8.3
	//ЗаписьJSON = Новый ЗаписьJSON;
	//ЗаписьJSON.ОткрытьФайл(ФайлКОтправке);
	//
	//ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
	
	Возврат ФайлКОтправке;
КонецФункции

Функция ПреобразоватьJSON_ВСтруктуру(СтрокаJSON)
	Перем Результат;
	//	ЧтениеJSON = Новый ЧтениеJSON;
	//	ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
	//	
	//	// Типовая функция разбора JSON
	//	Попытка
	//		Результат = ПрочитатьJSON(ЧтениеJSON);
	//	Исключение
	//		Результат = Неопределено;
	//	КонецПопытки;
	Попытка
		Результат = асПрочитатьJSON(СтрокаJSON);
	Исключение КонецПопытки;	
	
	Возврат Результат;	
КонецФункции



// Проверка заполнения реквизитов объекта по переданной структуре элементов
Функция ВсеРеквизитыЗаполнены(СтруктураПолей, ИмяДействия = "", Сообщать = Истина)
	
	ВсеЗаполнены = Истина;
	Для каждого Поле из СтруктураПолей Цикл
		Если НЕ ЗначениеЗаполнено(ЭтотОбъект[Поле.Ключ].Значение) Тогда
			Если Сообщать Тогда 
				#Если Клиент Тогда
					Сообщить("Для выполнения функции: " + ИмяДействия + " - необходимо заполнить поле: " + Поле.Ключ);
				#КонецЕсли
			КонецЕсли;
			ВсеЗаполнены = Ложь;
		КонецЕсли;
	КонецЦикла;
	
	Возврат ВсеЗаполнены;	
КонецФункции


#Если Клиент Тогда
	
Процедура НастроитьСтраницыПанелиПользователя(ФормаОтчета, Кнопка) Экспорт
	
	ФормаНастройкиПанелиПользователя = ПолучитьФорму("ФормаНастройкиПанелиПользователя", ФормаОтчета);
	
	ФормаНастройкиПанелиПользователя.ЗакрыватьПанельПриФормированииОтчета = ФормаОтчета.НастройкиФормы.ЗакрыватьПанельПриФормированииОтчета;
	ФормаНастройкиПанелиПользователя.ТаблицаСтраниц                       = ПолучитьТаблицуСтраниц(ФормаОтчета);
	Если ФормаНастройкиПанелиПользователя.ОткрытьМодально() = КодВозвратаДиалога.ОК Тогда
		ТаблицаСтраниц = ФормаНастройкиПанелиПользователя.ТаблицаСтраниц;
		ОбработкаИзмененияТаблицыСтраниц(ФормаОтчета, ТаблицаСтраниц);
		ФормаОтчета.НастройкиФормы.ЗакрыватьПанельПриФормированииОтчета = ФормаНастройкиПанелиПользователя.ЗакрыватьПанельПриФормированииОтчета;
	КонецЕсли;	
	
КонецПроцедуры

Функция ПолучитьТаблицуСтраниц(ФормаОтчета) Экспорт 
	
	ЭлементыФормы = ФормаОтчета.ЭлементыФормы;
	
	ТаблицаСтраниц = Новый ТаблицаЗначений;
	ТаблицаСтраниц.Колонки.Добавить("Использование");
	ТаблицаСтраниц.Колонки.Добавить("Страница");
	ТаблицаСтраниц.Колонки.Добавить("Представление");
	ТаблицаСтраниц.Колонки.Добавить("Высота");
	ТаблицаСтраниц.Колонки.Добавить("Раскрыта");
	
	Для Каждого Страница Из ЭлементыФормы.ПанельЗакладок.Страницы Цикл
		НоваяСтрока = ТаблицаСтраниц.Добавить();
		НоваяСтрока.Использование = Страница.Видимость;
		НоваяСтрока.Представление = Страница.Заголовок;
		НоваяСтрока.Страница      = Страница.Имя;
		НоваяСтрока.Раскрыта      = Страница.Раскрыта;
	КонецЦикла;
	
	Возврат ТаблицаСтраниц;
	
КонецФункции

Процедура ОбработкаИзмененияТаблицыСтраниц(ФормаОтчета, ТаблицаСтраниц) Экспорт
	
	ЭлементыФормы = ФормаОтчета.ЭлементыФормы;
	
	Если ТипЗнч(ТаблицаСтраниц) = Тип("ТаблицаЗначений") Тогда	
		ЭлементыФормы.ПанельЗакладок.РежимПрокручиваемыхСтраниц = Ложь;
		Индекс = 0;
		Для Каждого СтрокаТаблицы Из ТаблицаСтраниц Цикл
			СтраницыПанели = ЭлементыФормы.ПанельЗакладок.Страницы;
			Страница = СтраницыПанели[СтрокаТаблицы.Страница];
			Страница.Видимость = СтрокаТаблицы.Использование; 
			Страница.Раскрыта  = СтрокаТаблицы.Раскрыта;
			
			ТекущаяПозиция = СтраницыПанели.Индекс(Страница);
			Если ТекущаяПозиция <> Индекс Тогда
				СтраницыПанели.Сдвинуть(Страница, Индекс - ТекущаяПозиция);
			КонецЕсли;
			Индекс = Индекс + 1;
		КонецЦикла;
		Если ФормаОтчета.НастройкиФормы.Свойство("ТаблицаЭлементов") Тогда
			Для Каждого ЭлементУправления Из ФормаОтчета.НастройкиФормы.ТаблицаЭлементов Цикл
				Элемент = ЭлементыФормы[ЭлементУправления.Элемент];
				Если Элемент.Верх <> ЭлементУправления Тогда
					Элемент.Верх = ЭлементУправления.Верх;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
		ЭлементыФормы.ПанельЗакладок.РежимПрокручиваемыхСтраниц = Истина;
	КонецЕсли;
	
КонецПроцедуры

Функция ВосстановитьНастройкиФормы(ФормаОбработки, ВсеНастройки = Истина) Экспорт
	
	ЭлементыФормы = ФормаОбработки.ЭлементыФормы;
	НастройкиФормы = ФормаОбработки.НастройкиФормы;
	
	Если ВсеНастройки Тогда
		Если НастройкиФормы = Неопределено Тогда
			НастройкиФормы = Новый Структура;
		КонецЕсли;
		
		Если НастройкиФормы.Свойство("ТаблицаСтраниц") Тогда
			ОбработкаИзмененияТаблицыСтраниц(ФормаОбработки, НастройкиФормы.ТаблицаСтраниц);
		КонецЕсли;
		
		Если Не НастройкиФормы.Свойство("ЗакрыватьПанельПриФормированииОтчета") Тогда
			НастройкиФормы.Вставить("ЗакрыватьПанельПриФормированииОтчета", Ложь);
		КонецЕсли;
		
		Если НастройкиФормы.Свойство("ПанельНастроекПометка") Тогда
			ЭлементыФормы.КоманднаяПанельНастройки.Кнопки.Настройки.Пометка = НастройкиФормы.ПанельНастроекПометка;
		КонецЕсли;
		
		Если Не НастройкиФормы.Свойство("ШиринаПанельНастроек") Тогда
			НастройкиФормы.Вставить("ШиринаПанельНастроек", 281);
		КонецЕсли;
		
		Если Не НастройкиФормы.Свойство("ПоказатьОписание") Тогда
			НастройкиФормы.Вставить("ПоказатьОписание", Истина);
		КонецЕсли;
	КонецЕсли;
	
	ФормаОбработки.НастройкиФормы = НастройкиФормы;
	
КонецФункции

Процедура СохранитьНастройкиФормы(ФормаОбработки) Экспорт
	
	ЭлементыФормы = ФормаОбработки.ЭлементыФормы;
	НастройкиФормы = ФормаОбработки.НастройкиФормы;
	
	Если ЭлементыФормы.Найти("ПанельНастроек")<>Неопределено Тогда
		НастройкиФормы.Вставить("ПанельНастроекПометка", ЭлементыФормы.КоманднаяПанельНастройки.Кнопки.Настройки.Пометка);
		НастройкиФормы.Вставить("ШиринаПанельНастроек" , ЭлементыФормы.ПанельНастроек.Ширина);
	КонецЕсли;
	
	НастройкиФормы.Вставить("ТаблицаСтраниц"           , ПолучитьТаблицуСтраниц(ФормаОбработки));
	
	НастройкиФормы.Вставить("ПоказатьОписание"         , ЭлементыФормы.КоманднаяПанельСписокЗадач.Кнопки.ПоказатьСкрытьОписание.Пометка);

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

#КонецЕсли


Процедура УстановитьПоляЗадачиПоУмолчанию() Экспорт
	
	ЗадачаТрекер			= "Bug";
	ЗадачаСтатус			= "New";
	ЗадачаПриоритет			= "Normal";
	ЗадачаТема				= "";
	ЗадачаОписание			= "";
	
	ЗадачаНачалоВыполнения	= '0001-01-01';
	ЗадачаКонецВыполнения	= '0001-01-01';
	
	ЗадачаИсполнитель		= "";
	ЗадачаОценкаВремени		= 0;
	ЗадачаНомерРродительскойЗадачи		= 0;
	
	ЗадачаЗатраченноеВремя	= 0;
	ЗадачаКомментарии		= "";
	
	Вложения.Очистить();
	НастраиваемыеПоля.Очистить();
	Наблюдатели.Очистить();

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


// Заполнение списков выбора полей
//
Процедура ЗаполнитьСписокВыбораЭлементаФормы(Форма, ИмяПоля, Ресурс, Ключ="", ДопМассив=Неопределено) Экспорт
	
	Если Ключ = "" Тогда
		Ключ = Ресурс;
	КонецЕсли;
	
	//: ЗагруженныеДанные = Новый Соответствие
	Данные = ЗагруженныеДанные.Получить(Ключ);
	Если Данные = Неопределено Тогда
		Если Не ЗначениеЗаполнено(APIkey) Тогда
			Возврат;	
		КонецЕсли;
		
		ОтчетОВыполнении = СформироватьСтруктуруОтчетаОВыполнении();
		Данные = ПолучитьДанныеРесурсаИзТрекера(Ресурс, ОтчетОВыполнении);
		
		Если ОтчетОВыполнении.ЕстьОшибки Тогда
			Сообщить(ОтчетОВыполнении.ТекстОшибки);
			Возврат;
		КонецЕсли;
		ЗагруженныеДанные.Вставить(Ключ, Данные);
	КонецЕсли;
	
	ВариантыВыбора = Новый СписокЗначений;
	Если ДопМассив <> Неопределено Тогда
		Для Каждого Эл Из ДопМассив Цикл
			ВариантыВыбора.Добавить(Эл);
		КонецЦикла;
	КонецЕсли;
	
	Для Каждого Вариант Из Данные[Ключ] Цикл
		 ВариантыВыбора.Добавить(Вариант.name);
	КонецЦикла;
	
	Форма.ЭлементыФормы[ИмяПоля].СписокВыбора = ВариантыВыбора;
	
КонецПроцедуры


Функция ПолучитьТекстИнициализацииКовертераВПолеHTML() Экспорт
	
	Если НЕ ЗначениеЗаполнено(мКонвертерTextileToHTML) Тогда
		Возврат "";
	КонецЕсли;
	
	ТекстHTML =
	"<!DOCTYPE html> 
	|<html>
	|	<head>
	|	  	<meta http-equiv=""X-UA-Compatible"" content=""IE=9"" charset=""utf-8"" />
	|		<script type=""text/javascript"" src="+ФорматированиеПути(мКонвертерTextileToHTML)+"></script>
	|		<script type='text/javascript'>
	|		function TextileToHTML() 
	|		{
	|		var text=document.getElementById(""txt"").innerHTML;
	|		// для передачи значения в 1С используем элемент ""BufferData""
	|		document.getElementById(""BufferData"").innerHTML = textile(text);
	|		}
	|		</script>	
	|	</head> 
	|	<body>
	|		<p><input type=""text"" style=""display:none"" id=""txt"" maxlength=""1000"" size=""40"" value=""Введите текст в формате: <pre> *Textile* </pre>""/></p>
	|		<input type=""button"" style=""display:none"" onClick=""TextileToHTML()"" name=""b_exec"" id=""SendEvent"" value=""Execute""/> 
	|		<p><div id=""BufferData""></div></p>
	|	</body> 
	|</html>";
	
	Возврат ТекстHTML;
КонецФункции

Функция ФорматированиеПути(Путь)
	Возврат СтрЗаменить(Путь, "\", "/");
КонецФункции

// РАБОТА С БУФЕРОМ ОБМЕНА

Функция ПолучитьТекстИзБуфераОбмена() Экспорт
  #Если Клиент Тогда
    Объект = Новый COMОбъект("htmlfile");
    Возврат Объект.ParentWindow.ClipboardData.Getdata("Text");
  #КонецЕсли
КонецФункции

Процедура ВставитьТекстВБуферОбмена(СодержимоеВБуферОбмена) Экспорт
  #Если Клиент Тогда
    Если (ТипЗнч(СодержимоеВБуферОбмена) = Тип("Строка")) И (СокрЛП(СодержимоеВБуферОбмена) <> "") Тогда
      Объект = Новый COMОбъект("htmlfile");
      Объект.ParentWindow.ClipboardData.Setdata("Text", СодержимоеВБуферОбмена);
    КонецЕсли;
  #КонецЕсли
КонецПроцедуры

// СЛУЖЕБНЫЕ ПРОЦЕДУРЫ и ФУНКЦИИ

// Служебная функция, предназначенная для получения описания типов строки, заданной длины.
// 
// Параметры:
//  ДлинаСтроки - число, длина строки.
//
// Возвращаемое значение:
//  Объект "ОписаниеТипов" для строки указанной длины.
//
Функция ПолучитьОписаниеТиповСтроки(ДлинаСтроки) Экспорт

	Возврат Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(ДлинаСтроки, ДопустимаяДлина.Переменная));

КонецФункции // ПолучитьОписаниеТиповСтроки()

// Служебная функция, предназначенная для получения описания типов числа, заданной разрядности.
// 
// Параметры:
//  Разрядность 			- число, разряд числа.
//  РазрядностьДробнойЧасти - число, разряд дробной части.
//
// Возвращаемое значение:
//  Объект "ОписаниеТипов" для числа указанной разрядности.
//
Функция ПолучитьОписаниеТиповЧисла(Разрядность, РазрядностьДробнойЧасти = 0, ЗнакЧисла = Неопределено) Экспорт

	Если ЗнакЧисла = Неопределено Тогда
		КвалификаторЧисла = Новый КвалификаторыЧисла(Разрядность, РазрядностьДробнойЧасти);
	Иначе
		КвалификаторЧисла = Новый КвалификаторыЧисла(Разрядность, РазрядностьДробнойЧасти, ЗнакЧисла);
	КонецЕсли;

	Возврат Новый ОписаниеТипов("Число", КвалификаторЧисла);

КонецФункции // ПолучитьОписаниеТиповЧисла()

// Служебная функция, предназначенная для получения описания типов даты
// 
// Параметры:
//  ЧастиДаты - системное перечисление ЧастиДаты.
// 
Функция ПолучитьОписаниеТиповДаты(ЧастиДаты) Экспорт

	Возврат Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты));

КонецФункции // ПолучитьОписаниеТиповДаты()

// Добавляет в таблицу значений строки из другой таблицы значений и 
// в них значения колонок с совпадающими наименованиями.
//
// Параметры:
//  ТаблицаИсточник - таблица значений или массив строк таблицы значений, откуда берутся значения.
//  ТаблицаПриемник - таблица значений, куда добавляются строки.
//  ЗаполнятьНомераСтрокПоИсточнику - Булево - определяет необходимость сохранения информации
//		об индексах строк таблицы-источника в таблице-приемнике.
//		Используется в тех случаях, когда необходимо выполнить сопоставление строк приемника и источника.
//
Процедура ЗагрузитьВТаблицуЗначений(ТаблицаИсточник, ТаблицаПриемник, ЗаполнятьНомераСтрокПоИсточнику = Ложь) Экспорт
	
	// Заполним значения в совпадающих колонках.
	Для Каждого СтрокаТаблицыИсточника Из ТаблицаИсточник Цикл
		
		СтрокаТаблицыПриемника = ТаблицаПриемник.Добавить();
		ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтрокаТаблицыИсточника);
		
		Если ЗаполнятьНомераСтрокПоИсточнику Тогда
			СтрокаТаблицыПриемника.НомерСтроки = СтрокаТаблицыИсточника.Владелец().Индекс(СтрокаТаблицыИсточника);
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры // ЗагрузитьВТаблицуЗначений()

#Область JSON_ПАРСЕР_И_СЕРИАЛИЗАТОР

//{ 1С:JSON. JavaScript Object Notation парсер и сериализатор.

// Copyright © 2010-2013 Александр Переверзев

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

// Указанное выше уведомление об авторском праве и данные условия должны быть 
// включены во все копии или значимые части данного Программного Обеспечения.

// ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО 
// ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ 
// ГАРАНТИЯМИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И 
// ОТСУТСТВИЯ НАРУШЕНИЙ ПРАВ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ 
// ОТВЕТСТВЕННОСТИ ПО ИСКАМ О ВОЗМЕЩЕНИИ УЩЕРБА, УБЫТКОВ ИЛИ ДРУГИХ ТРЕБОВАНИЙ ПО 
// ДЕЙСТВУЮЩИМ КОНТРАКТАМ, ДЕЛИКТАМ ИЛИ ИНОМУ, ВОЗНИКШИМ ИЗ, ИМЕЮЩИМ ПРИЧИНОЙ ИЛИ 
// СВЯЗАННЫМ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ 
// ИЛИ ИНЫМИ ДЕЙСТВИЯМИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.


// Александр Переверзев
// e-mail: a.v.pereverzev@gmail.com
// Версия: 2.0.0.17


// Особенности:
//	Парсер и сериализатор поддерживают два режима (формата) работы:
//		- Стандартный – полная поддержка стандарта JSON (подробнее см. <http://www.JSON.org/> и 
//		  <http://www.ietf.org/rfc/rfc4627.txt?number=4627>);
//		- Альтернативный – направлен на применение в проектах подразумевающих постоянный двусторонний
//		  обмен данными, по каналам связи Интернет, и требующих повышенную скорость обработки данных,
//		  минимизацию пересылаемых пакетов данных и однозначную идентификацию ссылочных типов во входящих данных.
//
//	Независимо от режима работы сериализатор, по требованию (см. Настройки), позволяет автоматически передавать 
//	не только уникальный идентификатор ссылки, но и ее представление, а парсер в свою очередь, 
//	анализируя входные данные, опускает представления ссылок, не включая их в результирующий набор данных.
//
//	При работе с проектами, в исходящих строковых данных которых не гарантируется отсутствие символов из диапазонов:
//		[0x007f, 0x009f], 0x00ad, [0x0600, 0x0604], 0x070f, [0x17b4, 0x17b5], 
//		[0x200c, 0x200f], [0x2028, 0x202f] [0x2060, 0x206f], 0xfeff, [0xfff0, 0xffff], 
//	рекомендуется не отключать настройку (см. Настройки) полного маскирования символов 
//	(подробнее см. <https://github.com/douglascrockford/JSON-js/blob/master/json2.js> и <http://sadesign.ru/tools/unicode>).
//
//	Независимо от режима работы сериализатор, по требованию (см. Настройки), может маскировать кириллические символы 
//	современных алфавитов славянских языков "АБВГҐДЂЃЕЀЁЄЖЗЅИЍІЇЙЈКЛЉМНЊОПРСТЋЌУЎФХЦЧЏШЩЪЫЬЭЮЯ" (включая нижний регистр) 
//	(подробнее см. <http://ru.wikipedia.org/wiki/Кириллица> и <http://ru.wikipedia.org/wiki/Кириллица_в_Юникоде>).
//
//	Поддерживаются все среды исполнения с ограничением сериализуемых типов. Используется кроссплатформенный код.



// История изменения:
//	Версия 2.0.0.17:
//		- (Новое) Маскирование кириллических символов современных алфавитов славянских языков (по требованию);
//		- (Новое) Поддержка сериализатором типов: ДвоичныеДанные, Картинка, ХранилищеЗначения;
//		- (Изменение) Рефакторинг переменных и процедур;
//		- (Исправление) Сериализация типа COMSafeArray;
//		- (Исправление) Удалены лишние ключевые слова "Экспорт".
//		- (Оптимизация) Уменьшение проверок связанных с режимом и параметрами парсинга и сериализцаии;
//		- (Оптимизация) Проверка необходимости анализа форматирования вынесена из процедуры анализа форматирования;
//		- (Оптимизация) Изменен алгоритм автоматического приведение объекта к структуре или соответствию в зависимости от имен свойств;
//		- (Оптимизация) Отказ от явного приведения типов в пользу неявного в операторах условий;
//		- (Оптимизация) Отказ от оператора "Попытка Исключение" при преобразовании строки к уникальному идентификатору;
//		- (Оптимизация) Изменен порядок проверки типов при парсинге.
//	Версия 2.0.0.15
//		- Релиз.



// Методы:
//	ПрочитатьJSON – парсер;
//	ЗаписатьJSON – сериализатор.

// Настройки и параметры:
//
//	Параметры функций:
//		Стандарт – определяет режим работы парсера и сериализатора:
//			- Истина		– стандартный режим (значение по умолчанию);
//			- Ложь			– альтернативный режим;
//			- Неопределено	– автоматическое определение режима входящих данных
//							  (только парсер, не рекомендуется – влияет на производительность).
//
//		ПредставленияСсылок – позволяет автоматически передавать не только значение ссылки, но и ее представление:
//			- Истина		- ссылка парсится и сериализуется как объект с двумя свойствами "Ссылка" и "Представление";
//			- Ложь			- ссылка парсится и сериализуется как уникальный идентификатор ссылки (значение по умолчанию);
//			- Неопределено	– автоматическое определение формата ссылок во входящих данных
//							  (только парсер, не рекомендуется – влияет на производительность).
//
//	Настройки:
//		АвтоматическоеПриведениеОбъектаКСтруктуре – автоматическое приведение объекта к структуре, а не к соответствию.
//			Настройка изменяется в функции "АвтоматическоеПриведениеОбъектаКСтруктуре" (по умолчанию отключена).
//			Автоматическое приведение к структуре выполняется только для объектов имена свойств, которых могут быть 
//			использованы как ключи структуры, все остальные объекты преобразуются в соответствие.
//
//		ПолноеМаскированиеСимволов – маскирование символов некорректно обрабатываемых JavaScript-ом.
//			Настройка изменяется в функции "НастройкаПолноеМаскированиеСимволов" (по умолчанию включена).
//			Не рекомендуется к использованию, так как влияет на производительность, но гарантирует безопасную передачу данных.
//			Маскирование специальных символов из диапазона [0x0000, 0x001f] выполняется в не зависимости от настройки.
//
//		МаскированиеКириллицы – маскирование кириллических символов современных алфавитов славянских языков.
//			Настройка изменяется в функции "НастройкаМаскированиеКириллицы" (по умолчанию отключена).
//			Не рекомендуется к использованию, так как влияет на производительность.
//			Маскирование специальных символов из диапазона [0x0000, 0x001f] выполняется в не зависимости от настройки.
//
//		НеявноеПриведениеПримитивныхЗначенийКлюча – неявное приведение примитивных значений ключей соответствий к строке.
//			Настройка изменяется в функции "НеявноеПриведениеПримитивныхЗначенийКлюча" (по умолчанию отключена).


// Альтернативный режим:
//		- Не поддерживается форматирование, как во входящих, так и в исходящих данных;
//		- Сериализация ссылочных типов в строковое служебное представление.


// Приятности:
//	Парсер:
//		- Устойчивость к некорректным данным и не подверженность injection атакам;
//		- Продвинутый синтаксический анализатор (указывает место и тип ошибки в данных);
//		- Поддержка форматирования во входящих данных (только стандартный режим);
//		- Безопасный разбор форматирования - незамаскированные символы форматирования в строковых значениях не будут утеряны;
//		- Поддержка строк в одинарных и в двойных кавычках;
//		- Автоматическое приведение объекта к структуре или соответствию в зависимости от имен свойств¹;
//		- Автоматическое преобразование к типу Дата строки вида "9999-99-99T99:99:99Z";
//		- Автоматическое преобразование к типу УникальныйИдентификатор строки вида "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
//		- Автоматического определение режима (стандартного или альтернативного) входящих данных;
//		- Автоматического определение необходимости отсечения представления ссылок;
//		- Однозначная идентификация ссылок (только альтернативный режим).
//	Сериализатор:
//		- Поддержка форматирования исходящих данных (только стандартный режим);
//		- Широкий состав сериализуемых типов данных, в том числе ссылок;
//		- Автоматическое приведение значений ключей соответствий к строковому представлению в формате 1С²;
//		- Автоматическое преобразование неподдерживаемых типов к строке;
//		- Маскирование кириллических символов современных алфавитов славянских языков;
//		- Нечувствительность к локализации³.
// ----
//  ¹ Если все имена свойства входящего объекта могут быть использованы как ключи структуры, 
//    то такой объект будет автоматически приведен к структуре, а не к соответствию. Управляется настройкой.
//  ² Управляется настройкой.
//  ³ При сериализации некоторых типов, исходящие объекты которых имеют обязательные свойства, 
//    такие представления и имена таких свойств всегда имеют русскую локализацию.


// Неприятности:
//		- Нестандартно форматированный код (Alt+Shift+F в помощь) на гране читаемости; 
//		- Сериализатор ориентирован, на средние-крупные пакеты данных.

// Сериализуемые типы:
//	Сервер, толстый клиент, тонкий клиент, веб-клиент:
//		- Неопределено;
//		- Null;
//		- Примитивные типы (все);
//		- Универсальные коллекции значений (клиентские);
//		- УникальныйИдентификатор;
//		- ДвоичныеДанные;
//		- Картинка.
//	Сервер, толстый клиент:
//		- Универсальные коллекции значений (серверные);
//		- ЛюбаяСсылка;
//		- Запрос;
//		- РезультатЗапроса;
//		- ВыборкаИзРезультатаЗапроса;
//		- ПостроительЗапроса;
//		- ПостроительОтчета;
//		- ХранилищеЗначения.
//	Сервер:
//		- ДанныеФормыКоллекция;
//		- ДанныеФормыСтруктураСКоллекцией;
//		- ДанныеФормыДерево.

// Порядок сериализации типов:
//		- Неопределено - сериализуется как Null;
//		- Null - согласно стандарту;
//		- Примитивные типы - согласно стандарту;
//		- Массивы и COMSafeArray - массив, согласно стандарту:
//				[ Значение, ... ]
//
//		- Структуры и соответствия – объект, согласно стандарту;
//				{ Ключ:Значение, ... }
//
//		- СписокЗначений - массив объектов с тремя свойствами "Значение", "Представление" и "Пометка";
//				[ { "Значение":Значение, "Представление":Представление, "Пометка":Пометка }, ... ]
//
//		- КлючИЗначение - объект с двумя свойствами "Ключ" и "Значени";
//				{ "Ключ":Ключ, "Значение":Значение }
//
//		- ТаблицаЗначений - массив объектов: 
//				[ { Колонка:Значение, ... }, ... ]
//
//		- ДеревоЗначений - массив объектов с обязательным свойством "Строки":
//				[ { Колонка:Значение, ... , "Строки":[ { Колонка:Значение, ... , "Строки":[ ... ] } , ... ] }, ... ]
//
//		- УникальныйИдентификатор - приведение к строке вида "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
//
//		- ЛюбаяСсылка:
//			- Стандартный режим - получение уникального идентификатора ссылки (в том числе и для перечислений) и его сериализация;
//			- Альтернативный режим - приведение к строке служебного вида "¦ref¦ ... ¦";
//
//		  При сериализации ссылок в режиме автоматически передачи не только сериализованного значения ссылки, 
//		  но и ее представления. Каждая ссылка передается как объект с двумя свойствами "Ссылка" и "Представление";
//				{ "Ссылка":Ссылка, "Представление":Представление }
//
//		- Запрос - автоматически выполняется и сериализуется как таблица значений;
//		- РезультатЗапроса - сериализуется как таблица значений;
//		- ВыборкаИзРезультатаЗапроса - сериализуется как структура значений текущей запись результата запроса;
//		- ПостроительЗапроса - автоматически выполняется и сериализуется как таблица значений;
//		- ПостроительОтчета - автоматически выполняется и сериализуется как таблица значений;
//		- ДанныеФормыКоллекция - сериализуется как таблица значений;
//		- ДанныеФормыСтруктураСКоллекцией - сериализуется как таблица значений;
//		- ДанныеФормыДерево - сериализуется как дерево значений;
//		- ДвоичныеДанные - кодируется по алгоритму base64¹ и сериализуется как строка;
//		- Картинка - автоматически преобразуется и сериализуется как двоичные данные;
//		- ХранилищеЗначения - автоматически извлекается сохраненное значение и сериализуется в зависимости от типа извлеченного значения.
// ----
//  ¹ Следуя рекомендациям стандарта, сериализатор при кодировании по алгоритму base64, не добавляет переводы строк 
//    в результирующие данные (подробнее см. <http://tools.ietf.org/html/rfc4648#section-3.1>).

// Производительность:
//	Производительность парсера исключительно зависит от набора входящих данных, а также от наличия форматирования.
//	Наихудшим вариантом является форматированный массив чисел, наилучшим - неформатированный массив строк.
//
//	Intel Core 2 Duo T5870 @ 2GHz - форматированный массив со всеми приблизительно равномерно встречающимися типами данных:
//		Парсер:			35 Кбайт/с.
//		Сериализатор:	165 Кбайт/с.

// Примечание:
//	Мало комментариев - без комментариев.

// Всем удачного программирования :)


// ─────────────────────────────────────────────────────────────────────────────
//	JSON

// JSON парсер.
//
// Параметры:
//	Значение - Строка. Строка данных в формате JSON для парсинга;
//
//  Стандарт - Неопределено, Булево. Режим работы:
//		- Истина - стандартный режим (значение по умолчанию);
//		- Ложь - альтернативный режим;
//		- Неопределено - автоопределение режима;
//
//  ПредставленияСсылок - Неопределено, Булево. Режим передачи ссылочных типов, с их представлением или без:
//		- Истина - ссылки передаются вместе со своим представлением, как объекты с двумя свойствами содержащими саму ссылку и ее представление;
//		- Ложь - ссылки передаются без представления (значение по умолчанию).
//		- Неопределено - автоопределение режима.
// 
// Возвращаемое значение:
//  Набор данных согласно содержимому входящих данных. 
//
Функция асПрочитатьJSON(Значение, Стандарт = Истина, ПредставленияСсылок = Ложь) Экспорт 
	
	Возврат jsonПрочитатьИнициализация(Значение, Стандарт, ПредставленияСсылок);
	
КонецФункции // ПрочитатьJSON()

// JSON сериализатор.
//
// Параметры:
//	Значение. Набор данных сериализуемых в формат JSON;
//
//  Стандарт - Булево. Режим работы:
//		- Истина - стандартный режим (значение по умолчанию);
//		- Ложь - альтернативный режим;
//
//  ПредставленияСсылок - Булево. Режим передачи ссылочных типов, с их представлением или без:
//		- Истина - ссылки передаются вместе со своим представлением, как объекты с двумя свойствами содержащими саму ссылку и ее представление;
//		- Ложь - ссылки передаются без представления (значение по умолчанию).
// 
// Возвращаемое значение:
//  Строка. Строка данных в формате JSON согласно содержимому входящих данных. 
//
Функция асЗаписатьJSON(Значение, Стандарт = Истина, ПредставленияСсылок = Ложь) Экспорт 
	
	Возврат jsonЗаписатьИнициализация(Значение, Стандарт, ПредставленияСсылок);
	
КонецФункции // ЗаписатьJSON()


// ─────────────────────────────────────────────────────────────────────────────
//  НАСТРОЙКИ

// Функция управляющая настройкой "АвтоматическоеПриведениеОбъектаКСтруктуре".
//
// Возвращаемое значение:
//  Булево. Значение настройки:
//		- Истина - выполняется автоматическое приведение объекта к структуре; 
//		- Ложь - автоматическое приведение объекта к структуре не выполняется, все объекты преобразуются в соответствие. 
//
// Примечание:
//  Автоматическое приведение к структуре выполняется только для объектов имена свойств которых могут быть 
//  использованы как ключи структуры, все остальные объекты преобразуются в соответствие.
//
Функция НастройкаАвтоматическоеПриведениеОбъектаКСтруктуре()
	
	Возврат Истина;	// Измените для использования автоматического приведения объекта к структуре.
	
КонецФункции // НастройкаАвтоматическоеПриведениеОбъектаКСтруктуре()

// Функция управляющая настройкой "ПолноеМаскированиеСимволов".
//
// Возвращаемое значение:
//  Булево. Значение настройки:
//		- Истина - выполняется полное маскирование символов некорректно обрабатываемых JavaScript-ом; 
//		- Ложь - маскирование выполняется только согласно стандарту и дополнительно маскируются специальные символы. 
//
// Примечание:
//	Маскирование специальных символов из диапазона [0x0000, 0x001f] выполняется в не зависимости от настройки.
//
Функция НастройкаПолноеМаскированиеСимволов()
	
	Возврат Истина;	// Измените для неполного маскирования символов.
	
КонецФункции // НастройкаПолноеМаскированиеСимволов()

// Функция управляющая настройкой "МаскированиеКириллицы".
//
// Возвращаемое значение:
//  Булево. Значение настройки:
//		- Истина - выполняется маскирование кириллических символов; 
//		- Ложь - маскирование выполняется только согласно стандарту и дополнительно маскируются специальные символы. 
//
// Примечание:
//	Маскирование специальных символов из диапазона [0x0000, 0x001f] выполняется в не зависимости от настройки.
//
Функция НастройкаМаскированиеКириллицы()
	
	Возврат Ложь;	// Измените для маскирования кириллических символов.
	
КонецФункции // НастройкаМаскированиеКириллицы()

// Функция управляющая настройкой "НеявноеПриведениеПримитивныхЗначенийКлюча".
//
// Возвращаемое значение:
//  Булево. Значение настройки:
//		- Истина - выполняется неявное приведение примитивных типов значений ключей соответствий к их строковому представлению в формате 1С; 
//		- Ложь - неявное приведение примитивных типов значений ключей соответствий к строковому представлению не выполняется. 
//
// Примечание:
//	Неявно приводимые типы: Null, Булево, Число, Дата, Строка, УникальныйИдентификатор.
//
Функция НастройкаНеявноеПриведениеПримитивныхЗначенийКлюча()
	
	Возврат Ложь;	// Измените для использования неявного приведения примитивных значений ключей соответствий к строке.
	
КонецФункции // НастройкаНеявноеПриведениеПримитивныхЗначенийКлюча()


// ─────────────────────────────────────────────────────────────────────────────
//  ПАРСЕР

Функция jsonПрочитатьИнициализация(Значение, Знач Стандарт, Знач ПредставленияСсылок)
	
	// Проверка параметров.
	Если (Не Стандарт = Истина) И (Не Стандарт = Ложь) И (Не Стандарт = Неопределено) Тогда ВызватьИсключение ИсключениеНекорректныйПараметр("Стандарт"); КонецЕсли; 
	Если (Не ПредставленияСсылок = Истина) И (Не ПредставленияСсылок = Ложь) И (Не ПредставленияСсылок = Неопределено) Тогда ВызватьИсключение ИсключениеНекорректныйПараметр("ПредставленияСсылок"); КонецЕсли; 
	
	// Использование более общего случая параметров.
	Альтернативный = (Стандарт = Неопределено) Или (Не Стандарт); Стандарт = (Стандарт = Неопределено) Или Стандарт; ПредставленияСсылок = (ПредставленияСсылок = Неопределено) Или ПредставленияСсылок;
	
	// Схема подстановок шестнадцатиричной системы.
	СхемаПодстановок = Новый Соответствие; ШестнадцатиричнаяСистема = "0123456789abcdef"; ДесятичноеЧисло = 0;
	Для ВторойРазряд = 1 По 16 Цикл Для ПервыйРазряд = 1 По 16 Цикл СхемаПодстановок.Вставить(Сред(ШестнадцатиричнаяСистема, ВторойРазряд, 1) + Сред(ШестнадцатиричнаяСистема, ПервыйРазряд, 1), ДесятичноеЧисло); ДесятичноеЧисло = ДесятичноеЧисло + 1; КонецЦикла; КонецЦикла;
	
	// Вспомогательные данные.
	ВспомогательныеДанные = Новый Структура("ТипСтроки,СхемаПодстановок,АвтоматическиПриводитьКСтруктуре",
		Тип("Строка"),
		СхемаПодстановок,
		(НастройкаАвтоматическоеПриведениеОбъектаКСтруктуре() = Истина));
		
	// Стартовые значения.
	Индекс = 1; Длина = СтрДлина(Значение);
	
	// Форматирование (первый шаг парсера).
	Если Стандарт Тогда СимволыФорматирования = " " + Символы.ВК + Символы.ПС + Символы.Таб; jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли;
	Если (Индекс > Длина) Тогда ВызватьИсключение ИсключениеПустойПакетДанных(); КонецЕсли; 
	
	// Парсер.
	Возврат jsonПрочитать(Значение, Стандарт, Альтернативный, ПредставленияСсылок, Индекс, Длина, ВспомогательныеДанные, СимволыФорматирования, Истина);
	
КонецФункции // jsonПрочитатьИнициализация()

Функция jsonПрочитать(Значение, Стандарт, Альтернативный, ПредставленияСсылок, Индекс, Длина, ВспомогательныеДанные, СимволыФорматирования, ПервыйУровень)
	
	Символ = Сред(Значение, Индекс, 1);
	Если (Символ = """") Или (Символ = "'") Тогда        																	// " , '
		
		// Строка.
		Подстрока = Сред(Значение, Индекс + 1); Начало = Индекс; Пока Истина Цикл
			Позиция = Найти(Подстрока, Символ);
			
			Если (Позиция > 0) Тогда
				Индекс = Индекс + Позиция; Откат = Позиция - 1; Маскировка = Ложь; Пока (Сред(Подстрока, Откат, 1) = "\") И Откат Цикл Маскировка = Не Маскировка; Откат = Откат - 1; КонецЦикла;
				Если Маскировка Тогда Подстрока = Сред(Подстрока, Позиция + 1); Иначе Прервать; КонецЕсли;
			Иначе
		  		ВызватьИсключение ИсключениеНеожиданноеОкончаниеПакетаДанных();
			КонецЕсли;
			
		КонецЦикла;
		
		// Строка.
		Результат = jsonПрочитатьСтроку(Сред(Значение, Начало + 1, Индекс - Начало - 1), Стандарт, Начало, ВспомогательныеДанные.СхемаПодстановок, (Символ = "'"));
		
		Если jsonПрочитатьОпределитьДату(Результат) Тогда
			// Дата.
			Результат = jsonПрочитатьДату(Результат, Начало);
		ИначеЕсли jsonПрочитатьОпределитьИдентификатор(Результат) Тогда
			// Идентификатор.
			Результат = jsonПрочитатьИдентификатор(Результат, Начало);
		Иначе
			Если Альтернативный И jsonПрочитатьОпределитьВнутреннийТип(Результат) Тогда
				// Внутренний тип.
				Результат = jsonПрочитатьВнутреннийТип(Результат, Начало);
			КонецЕсли;
		КонецЕсли;
		
		// Корректировка индекса.
		Индекс = Индекс + 1;
		
	ИначеЕсли (Символ = "[") Тогда																							// [
		
		// Массив.
		Результат = Новый Массив;
		
		Индекс = Индекс + 1; Если Стандарт Тогда jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли; Если (Индекс > Длина) Тогда ВызватьИсключение ИсключениеНеожиданноеОкончаниеМассива(Длина); КонецЕсли;
		Символ = Сред(Значение, Индекс, 1); Если (Символ = "]") Тогда														// ] 
			
			// Пустой массив.
			Индекс = Индекс + 1;
		
		Иначе
		
			Пока (Индекс <= Длина) Цикл
				
				// Значение.
				Результат.Добавить(jsonПрочитать(Значение, Стандарт, Альтернативный, ПредставленияСсылок, Индекс, Длина, ВспомогательныеДанные, СимволыФорматирования, Ложь));
				
				Символ = Сред(Значение, Индекс, 1);
				Если (Символ = "]") Тогда																					// ]
					// Окончание массива.
					Индекс = Индекс + 1; Прервать;
				Иначе
					// Продолжение массива.
					Если (Символ = ",") Тогда																				// ,
						Индекс = Индекс + 1; Если Стандарт Тогда jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли; Если (Индекс >= Длина) Тогда ВызватьИсключение ИсключениеНеожиданноеОкончаниеМассива(Длина); КонецЕсли;
					Иначе
						ВызватьИсключение ИсключениеНедопустимыйСимвол(Индекс, ",");
					КонецЕсли;
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
		
	ИначеЕсли (Символ = "{") Тогда																							// {
	
		// Объект.
		Индекс = Индекс + 1; Если Стандарт Тогда jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли; Если (Индекс > Длина) Тогда ВызватьИсключение ИсключениеНеожиданноеОкончаниеМассива(Длина); КонецЕсли;
		Символ = Сред(Значение, Индекс, 1); Если (Символ = "}") Тогда														// } 
			
			// Пустой объект.
			Индекс = Индекс + 1;
			
			// Структура или соответствие.
			Если ВспомогательныеДанные.АвтоматическиПриводитьКСтруктуре Тогда Результат = Новый Структура; Иначе Результат = Новый Соответствие; КонецЕсли; 
		
		Иначе
			
			Результат = Новый Соответствие;
			
			ТипСтроки = ВспомогательныеДанные.ТипСтроки; Пока (Индекс <= Длина) Цикл
				
				// Ключ.
				Начало = Индекс; КлючЭлемента = jsonПрочитать(Значение, Стандарт, Альтернативный, ПредставленияСсылок, Индекс, Длина, ВспомогательныеДанные, СимволыФорматирования, Ложь); Если (Не ТипЗнч(КлючЭлемента) = ТипСтроки) Тогда ВызватьИсключение ИсключениеНедопустимыйТипКлюча(Начало, КлючЭлемента); КонецЕсли;
				
				Символ = Сред(Значение, Индекс, 1);
				Если (Символ = ":") Тогда																					// :
					Индекс = Индекс + 1; Если Стандарт Тогда jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли; Если (Индекс >= Длина) Тогда ВызватьИсключение ИсключениеНеожиданноеОкончаниеОбъетка(Длина); КонецЕсли;
				Иначе
					ВызватьИсключение ИсключениеНедопустимыйСимвол(Индекс, ":");
				КонецЕсли;
				
				// Значение.
				ЗначениеЭлемента = jsonПрочитать(Значение, Стандарт, Альтернативный, ПредставленияСсылок, Индекс, Длина, ВспомогательныеДанные, СимволыФорматирования, Ложь);
				
				// Коллекция.
				Результат.Вставить(КлючЭлемента, ЗначениеЭлемента);
				
				Символ = Сред(Значение, Индекс, 1);
				Если (Символ = "}") Тогда																					// }
					// Окончание объекта.
					Индекс = Индекс + 1; Прервать;
				Иначе
					// Продолжение объекта.
					Если (Символ = ",") Тогда																				// ,
						Индекс = Индекс + 1; Если Стандарт Тогда jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли; Если (Индекс >= Длина) Тогда ВызватьИсключение ИсключениеНеожиданноеОкончаниеОбъетка(Длина); КонецЕсли;
					Иначе
						ВызватьИсключение ИсключениеНедопустимыйСимвол(Индекс, ",");
					КонецЕсли;
				КонецЕсли;
				
			КонецЦикла;
			
			// Структура или соответствие.
			Если ВспомогательныеДанные.АвтоматическиПриводитьКСтруктуре Тогда
				
				РезультатСтруктура = Новый Структура; 
				Для Каждого Элемент Из Результат Цикл Попытка РезультатСтруктура.Вставить(Элемент.Ключ, Элемент.Значение); Исключение РезультатСтруктура = Результат; АвтоматическоеПриведениеНеВыполнено = Истина; Прервать; КонецПопытки; КонецЦикла;
				Результат = РезультатСтруктура;
				
				// Ссылка.
				Если ПредставленияСсылок Тогда Результат = jsonПрочитатьСсылку(Результат, (АвтоматическоеПриведениеНеВыполнено = Истина)); КонецЕсли;
				
			Иначе
				
				// Ссылка.
				Если ПредставленияСсылок Тогда Результат = jsonПрочитатьСсылку(Результат, Истина); КонецЕсли;
				
			КонецЕсли; 
		
		КонецЕсли;
		
	Иначе
	
		// Остальные примитивные типы.
		Если (Символ = "n") Тогда
			
			// Null.
			Если (Сред(Значение, Индекс, 4) = "null") Тогда Индекс = Индекс + 4; Результат = Null; Иначе ВызватьИсключение ИсключениеНекорректныйТипNull(Индекс); КонецЕсли;
			
		ИначеЕсли (Символ = "t") Тогда
			
			// Истина.
			Если (Сред(Значение, Индекс, 4) = "true") Тогда Индекс = Индекс + 4; Результат = Истина; Иначе ВызватьИсключение ИсключениеНекорректныйТипБулево(Индекс); КонецЕсли;
			
		ИначеЕсли (Символ = "f") Тогда
			
			// Ложь.
			Если (Сред(Значение, Индекс, 5) = "false") Тогда Индекс = Индекс + 5; Результат = Ложь; Иначе ВызватьИсключение ИсключениеНекорректныйТипБулево(Индекс); КонецЕсли;
			
		ИначеЕсли (Символ = "u") Тогда
			
			// Неопределено.
			Если (Сред(Значение, Индекс, 9) = "undefined") Тогда Индекс = Индекс + 9; Результат = Неопределено; Иначе ВызватьИсключение ИсключениеНекорректныйТипНеопределено(Индекс); КонецЕсли;
			
		Иначе
			
			// Число.
			Начало = Индекс; Пока Найти("-+0123456789.", Символ) И (Индекс <= Длина) Цикл Индекс = Индекс + 1; Символ = Сред(Значение, Индекс, 1); КонецЦикла;
			
			// Преобразование числа.
			Попытка
				Результат = Число(Сред(Значение, Начало, Индекс - Начало));
			Исключение
				ВызватьИсключение ИсключениеНекорректныйФорматЧисла(Начало, Сред(Значение, Начало, Индекс - Начало)); 
			КонецПопытки;
			
			// Экспоненциальная часть.
			Если (Символ = "E") Или (Символ = "e") Тогда
				
				// Степень.
				Индекс = Индекс + 1; Позиция = Индекс; Символ = Сред(Значение, Индекс, 1); Пока Найти("-+0123456789", Символ) И (Индекс <= Длина) Цикл Индекс = Индекс + 1; Символ = Сред(Значение, Индекс, 1); КонецЦикла;
				
				// Преобразование степени.
				Попытка
					Степень = Число(Сред(Значение, Позиция, Индекс - Позиция));
				Исключение
					ВызватьИсключение ИсключениеНекорректныйФорматЧисла(Начало, Сред(Значение, Начало, Индекс - Начало)); 
				КонецПопытки;
				
				// Возвидение числа в степень.
				Результат = Результат * Pow(10, Степень);
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Форматирование.
	Если Стандарт Тогда jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования); КонецЕсли; Если ПервыйУровень Тогда Если (Индекс <= Длина) Тогда ВызватьИсключение ИсключениеНекорректныйПакетДанных(Индекс); КонецЕсли; Иначе Если (Индекс > Длина) Тогда ВызватьИсключение ИсключениеНеожиданноеОкончаниеПакетаДанных(); КонецЕсли; КонецЕсли;
	
	Возврат Результат;
	
КонецФункции // jsonПрочитать()

Функция jsonПрочитатьОпределитьДату(Значение)

	// Проверка.
	Если (СтрДлина(Значение) = 20) Тогда
		Если (Сред(Значение, 05, 1) = "-") И				// -
			 (Сред(Значение, 08, 1) = "-") И				// -
			 (Сред(Значение, 11, 1) = "T") И				// T
			 (Сред(Значение, 14, 1) = ":") И				// :
			 (Сред(Значение, 17, 1) = ":") И				// :
			 (Сред(Значение, 20, 1) = "Z") Тогда			// Z
			// Год. 
			Если Найти("0123456789", Сред(Значение, 01, 1)) И
				 Найти("0123456789", Сред(Значение, 02, 1)) И
				 Найти("0123456789", Сред(Значение, 03, 1)) И
				 Найти("0123456789", Сред(Значение, 04, 1)) И
			// Месяц.
				 Найти("0123456789", Сред(Значение, 06, 1)) И
				 Найти("0123456789", Сред(Значение, 07, 1)) И
			// День.
				 Найти("0123456789", Сред(Значение, 09, 1)) И
				 Найти("0123456789", Сред(Значение, 10, 1)) И
			// Час.
				 Найти("0123456789", Сред(Значение, 12, 1)) И
				 Найти("0123456789", Сред(Значение, 13, 1)) И
			// Минута.
				 Найти("0123456789", Сред(Значение, 15, 1)) И
				 Найти("0123456789", Сред(Значение, 16, 1)) И
			// Секунда.
				 Найти("0123456789", Сред(Значение, 18, 1)) И
				 Найти("0123456789", Сред(Значение, 19, 1)) Тогда
				Возврат Истина; 
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции // jsonПрочитатьОпределитьДату()

Функция jsonПрочитатьОпределитьИдентификатор(Значение)

	// Проверка.
	Если (СтрДлина(Значение) = 36) Тогда
		Если (Сред(Значение, 09, 1) = "-") И					// -
			 (Сред(Значение, 14, 1) = "-") И					// -
			 (Сред(Значение, 19, 1) = "-") И					// -
			 (Сред(Значение, 24, 1) = "-") Тогда				// -
			// Первая часть. 
			Для Индекс = 01 По 08 Цикл Если Не Найти("0123456789ABCDEFabcdef", Сред(Значение, Индекс, 1)) Тогда Возврат Ложь; КонецЕсли; КонецЦикла;
			// Вторая часть. 
			Для Индекс = 10 По 13 Цикл Если Не Найти("0123456789ABCDEFabcdef", Сред(Значение, Индекс, 1)) Тогда Возврат Ложь; КонецЕсли; КонецЦикла;
			// Третья часть. 
			Для Индекс = 15 По 18 Цикл Если Не Найти("0123456789ABCDEFabcdef", Сред(Значение, Индекс, 1)) Тогда Возврат Ложь; КонецЕсли; КонецЦикла;
			// Четвертая часть. 
			Для Индекс = 20 По 23 Цикл Если Не Найти("0123456789ABCDEFabcdef", Сред(Значение, Индекс, 1)) Тогда Возврат Ложь; КонецЕсли; КонецЦикла;
			// Пятая часть. 
			Для Индекс = 25 По 36 Цикл Если Не Найти("0123456789ABCDEFabcdef", Сред(Значение, Индекс, 1)) Тогда Возврат Ложь; КонецЕсли; КонецЦикла;
			Возврат Истина;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции // jsonПрочитатьОпределитьИдентификатор()

Функция jsonПрочитатьОпределитьВнутреннийТип(Значение)
	
	// Поиск.
	Возврат (Лев(Значение, 1) = "¦") И (Сред(Значение, 5, 1) = "¦") И (Прав(Значение, 1) = "¦"); // ¦xxx¦ ... ¦
	
КонецФункции // jsonПрочитатьОпределитьВнутреннийТип()

Функция jsonПрочитатьСтроку(Значение, Стандарт, Индекс, СхемаПодстановок, ОдинарнаяКавычка)
	
	// Последоавтельность перемаскировки.
	ПоследоавтельностьПеремаскировки = "\" + Символ(65535);
	
	// Демаскирование служебных символов.
	Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Значение, 
						"\\",			ПоследоавтельностьПеремаскировки),		// Перемаскирование последовательности.
						"\/",			"/"),           // x2f
						"\b",			Символ(008)),	// x08
						"\t",			Символы.Таб),   // x09
						"\n",			Символы.ПС),    // x0a
						"\f",			Символы.ПФ),    // x0c
						"\r",			Символы.ВК),    // x0d
						"\""",			"""");          // x22
						
	// Демаскирование Юникод символов.
	Позиция = Найти(Результат, "\u"); Пока Позиция Цикл
		СтаршийБайт = СхемаПодстановок[НРег(Сред(Результат, Позиция + 2, 2))]; МладшийБайт = СхемаПодстановок[НРег(Сред(Результат, Позиция + 4, 2))]; Если (СтаршийБайт = Неопределено) Или (МладшийБайт = Неопределено) Тогда ВызватьИсключение ИсключениеНекорректныйФорматСтроки(Индекс); КонецЕсли;
		Результат = СтрЗаменить(Результат, Сред(Результат, Позиция, 6), Символ(256 * СтаршийБайт + МладшийБайт)); Позиция = Найти(Результат, "\u");
	КонецЦикла;
		
	// Одинарная кавычка.
	Если ОдинарнаяКавычка Тогда Результат = СтрЗаменить(Результат, "\'", "'"); КонецЕсли;
	
	// Демаскирование перемаскированой последовательности.
	Возврат СтрЗаменить(Результат, ПоследоавтельностьПеремаскировки, "\");				
						
КонецФункции // jsonПрочитатьСтроку()

Функция jsonПрочитатьДату(Значение, Индекс)
	
	// Поиск.
	Попытка
		Возврат Дата(Лев(Значение, 4) + Сред(Значение, 06, 2) + Сред(Значение, 09, 2) + 
					 Сред(Значение, 12, 2) + Сред(Значение, 15, 2) + Сред(Значение, 18, 2));
	Исключение
		ВызватьИсключение ИсключениеНекорректныйФорматДаты(Индекс, Значение);
	КонецПопытки;
	
КонецФункции // jsonПрочитатьДату()

Функция jsonПрочитатьСсылку(Значение, Соответствие)
	
	Перем Ссылка;
	
	// Ссылка.
	Если (Значение.Количество() = 2) Тогда 
		Если Соответствие Тогда
			Ссылка = Значение.Получить("Ссылка"); Если (Не Ссылка = Неопределено) И (Не Значение.Получить("Представление") = Неопределено) Тогда Возврат Ссылка; КонецЕсли;
		Иначе
			Если Значение.Свойство("Представление") И Значение.Свойство("Ссылка", Ссылка) Тогда Возврат Ссылка; КонецЕсли;
		КонецЕсли;
	КонецЕсли;	
	
	Возврат Значение;
	
КонецФункции // jsonПрочитатьСсылку()

Функция jsonПрочитатьИдентификатор(Значение, Индекс)
	
	// Поиск.
	Возврат Новый УникальныйИдентификатор(Значение);
	
КонецФункции // jsonПрочитатьИдентификатор()

Функция jsonПрочитатьВнутреннийТип(Значение, Индекс)
#Если ВебКлиент Или ТонкийКлиент Тогда
	ВызватьИсключение ИсключениеНевозможноПреобразоватьЗначениеНаКлиенте(Индекс, Значение);
#Иначе
	
	// Поиск.
	Тип = Сред(Значение, 2, 3); Данные = Сред(Значение, 6, СтрДлина(Значение) - 6);
	
	Если (Тип = "ref") Тогда
		Попытка
			Возврат ЗначениеИзСтрокиВнутр("{""#""," + СтрЗаменить(СтрЗаменить(Данные, "×", ":"), "÷", ",") + "}");
		Исключение
			ВызватьИсключение ИсключениеНевозможноПреобразоватьЗначение(Индекс, Значение);
		КонецПопытки;
	КонецЕсли;
		
	ВызватьИсключение ИсключениеНеопознанныйТип(Индекс, Тип);
	
#КонецЕсли
КонецФункции // jsonПрочитатьВнутреннийТип()

Процедура jsonПрочитатьПропуститьФорматирование(Значение, Стандарт, Индекс, Длина, СимволыФорматирования)
	
	// Пропуск форматирования.
	Пока (Индекс <= Длина) И Найти(СимволыФорматирования, Сред(Значение, Индекс, 1)) Цикл Индекс = Индекс + 1; КонецЦикла;
	// Пробел его не видно, \r, \n, \t .
	
КонецПроцедуры // jsonПрочитатьПропуститьФорматирование()


// ─────────────────────────────────────────────────────────────────────────────
//  СЕРИАЛИЗАТОР

Функция jsonЗаписатьИнициализация(Значение, Знач Стандарт, Знач ПредставленияСсылок)
	
	// Проверка параметров.
	Если (Не Стандарт = Истина) И (Не Стандарт = Ложь) Тогда ВызватьИсключение ИсключениеНекорректныйПараметр("Стандарт"); КонецЕсли; 
	Если (Не ПредставленияСсылок = Истина) И (Не ПредставленияСсылок = Ложь) Тогда ВызватьИсключение ИсключениеНекорректныйПараметр("ПредставленияСсылок"); КонецЕсли; 
	
	ВспомогательныеДанные = Новый Структура("ПримитивныеТипы,Массивы,Структуры,Соответсвия,Построители,КлиентскиеТипы,ТипДопустимыхКлючей", 
		Новый ОписаниеТипов("Null,Булево,Число,Дата,УникальныйИдентификатор"),									// ПримитивныеТипы.
		#Если ВебКлиент Или ТонкийКлиент Тогда
			Новый ОписаниеТипов("Массив,ФиксированныйМассив"),													// Массивы.
			Новый ОписаниеТипов("Структура,ФиксированнаяСтруктура"),											// Структуры.
			Новый ОписаниеТипов("Структура,ФиксированнаяСтруктура,Соответствие,ФиксированноеСоответствие"),		// Соответсвия.
		#Иначе
			#Если НаСервере Тогда
				Новый ОписаниеТипов("Массив,ФиксированныйМассив,ФиксированнаяКоллекция"),						// Массивы.
				Новый ОписаниеТипов("Структура,ФиксированнаяСтруктура"),										// Структуры.
				Новый ОписаниеТипов("Структура,ФиксированнаяСтруктура,Соответствие,ФиксированноеСоответствие"),	// Соответсвия.
			#Иначе
				Новый ОписаниеТипов("Массив,ФиксированныйМассив"),												// Массивы.
				Новый ОписаниеТипов("Структура"),																// Структуры.
				Новый ОписаниеТипов("Структура,Соответствие"),													// Соответсвия.
			#КонецЕсли
		#КонецЕсли
		#Если ВебКлиент Или ТонкийКлиент Тогда
			Неопределено,																						// Построители.
		#Иначе
			Новый ОписаниеТипов("ПостроительЗапроса,ПостроительОтчета"),										// Построители.
		#КонецЕсли
		#Если НаСервере Тогда
			Новый ОписаниеТипов("ДанныеФормыКоллекция,ДанныеФормыСтруктураСКоллекцией,ДанныеФормыДерево"),		// КлиентскиеТипы.
		#Иначе
			Неопределено,																						// КлиентскиеТипы.
		#КонецЕсли
		Новый ОписаниеТипов("Строка"));																			// ТипДопустимыхКлючей.
		
	// Типы допустимых ключей.
	Если (НастройкаНеявноеПриведениеПримитивныхЗначенийКлюча() = Истина) Тогда ВспомогательныеДанные.ТипДопустимыхКлючей = Новый ОписаниеТипов("Null,Булево,Число,Дата,Строка,УникальныйИдентификатор"); КонецЕсли;
		
	// форматирование.
	Если Стандарт Тогда Смещение = ""; Отступ = " "; Табуляция = "    "; ПереносСтроки = Символы.ПС; Иначе Смещение = ""; Отступ = ""; Табуляция = ""; ПереносСтроки = ""; КонецЕсли;
	
	// Сериализация.
	Возврат jsonЗаписать(Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, (НастройкаПолноеМаскированиеСимволов() = Истина), (НастройкаМаскированиеКириллицы() = Истина));
	
КонецФункции // jsonЗаписатьИнициализация()

Функция jsonЗаписать(Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы)
	
	// Определение типа.
	Тип = ТипЗнч(Значение);
		
	// Строка.
	Если (Тип = Тип("Строка")) Тогда Возврат jsonЗаписатьСтроку(Значение, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	
	// Неопределено и примитивные типы.
	Если ВспомогательныеДанные.ПримитивныеТипы.СодержитТип(Тип) Тогда 
		#Если ВебКлиент Или ТонкийКлиент Тогда
		Если (Значение = Null) Или (Значение = Неопределено) Тогда Возврат "null"; ИначеЕсли (Тип = Тип("Дата")) Тогда Возврат """" + Формат(Значение, "ДФ=yyyy-MM-ddTHH:mm:ss; ДП=") + "Z""" ИначеЕсли (Тип = Тип("УникальныйИдентификатор")) Тогда Возврат """" + Значение + """"; Иначе Возврат Формат(Значение, "ЧРД=.; ЧН=; ЧГ=; БЛ=false; БИ=true"); КонецЕсли;
		#Иначе
		Если (Значение = Null) Или (Значение = Неопределено) Тогда Возврат "null"; ИначеЕсли (Тип = Тип("Дата")) Тогда Возврат """" + XMLСтрока(Значение) + "Z""" ИначеЕсли (Тип = Тип("УникальныйИдентификатор")) Тогда Возврат """" + XMLСтрока(Значение) + """"; Иначе Возврат XMLСтрока(Значение); КонецЕсли;
		#КонецЕсли
	КонецЕсли;
	
	// Структуры и строка дерева значений (структурой).
	Если ВспомогательныеДанные.Структуры.СодержитТип(Тип) Тогда
		Если Значение.Количество() Тогда
						
			// форматирование.
			СледующееСмещение = Смещение + Табуляция;
	
			Если (Колонки = Неопределено) Тогда
			
				// Структуры.
				Если МаскированиеКириллицы Тогда
					
					Первый = Истина; Для Каждого Элемент Из Значение Цикл
						Если Первый Тогда
							Результат = ПереносСтроки + СледующееСмещение + jsonЗаписатьСтроку(Элемент.Ключ, ПолноеМаскированиеСимволов, МаскированиеКириллицы) + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
						Иначе
							Результат = Результат + "," + ПереносСтроки + СледующееСмещение + jsonЗаписатьСтроку(Элемент.Ключ, ПолноеМаскированиеСимволов, МаскированиеКириллицы) + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
						КонецЕсли;
					КонецЦикла;
					
				Иначе
					
					Первый = Истина; Для Каждого Элемент Из Значение Цикл
						Если Первый Тогда
							Результат = ПереносСтроки + СледующееСмещение + """" + Элемент.Ключ + """:" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
						Иначе
							Результат = Результат + "," + ПереносСтроки + СледующееСмещение + """" + Элемент.Ключ + """:" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
						КонецЕсли;
					КонецЦикла;
					
				КонецЕсли;

			Иначе
			
				// Строка дерева значений (структурой).
				Если МаскированиеКириллицы Тогда
					
					Первый = Истина; Для Каждого Элемент Из Значение Цикл
						Если (Элемент.Ключ = "Строки") Тогда Продолжить; КонецЕсли;
						Если Первый Тогда
							Результат = ПереносСтроки + СледующееСмещение + jsonЗаписатьСтроку(Элемент.Ключ, ПолноеМаскированиеСимволов, МаскированиеКириллицы) + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
						Иначе
							Результат = Результат + "," + ПереносСтроки + СледующееСмещение + jsonЗаписатьСтроку(Элемент.Ключ, ПолноеМаскированиеСимволов, МаскированиеКириллицы) + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
						КонецЕсли;
					КонецЦикла;
					Если Первый Тогда
						Результат = ПереносСтроки + СледующееСмещение + """\u0421\u0442\u0440\u043e\u043a\u0438"":" + Отступ + jsonЗаписать(Значение.Строки, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
					Иначе
						Результат = Результат + "," + ПереносСтроки + СледующееСмещение + """\u0421\u0442\u0440\u043e\u043a\u0438"":" + Отступ + jsonЗаписать(Значение.Строки, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
					КонецЕсли;
					
				Иначе
					
					Первый = Истина; Для Каждого Элемент Из Значение Цикл
						Если (Элемент.Ключ = "Строки") Тогда Продолжить; КонецЕсли;
						Если Первый Тогда
							Результат = ПереносСтроки + СледующееСмещение + """" + Элемент.Ключ + """:" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
						Иначе
							Результат = Результат + "," + ПереносСтроки + СледующееСмещение + """" + Элемент.Ключ + """:" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
						КонецЕсли;
					КонецЦикла;
					Если Первый Тогда
						Результат = ПереносСтроки + СледующееСмещение + """Строки"":" + Отступ + jsonЗаписать(Значение.Строки, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
					Иначе
						Результат = Результат + "," + ПереносСтроки + СледующееСмещение + """Строки"":" + Отступ + jsonЗаписать(Значение.Строки, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
					КонецЕсли;
					
				КонецЕсли;

		    КонецЕсли;
			Возврат "{" + Результат + ПереносСтроки + Смещение + "}";
			
		Иначе
			
			// Пустая структура.
			Возврат "{}";
		
		КонецЕсли;
	КонецЕсли;
	
	// Соответсвия.
	Если ВспомогательныеДанные.Соответсвия.СодержитТип(Тип) Тогда
		Если Значение.Количество() Тогда
						
			// форматирование.
			СледующееСмещение = Смещение + Табуляция;
	
			// Соответсвия.
			ТипДопустимыхКлючей = ВспомогательныеДанные.ТипДопустимыхКлючей;
			
			Если МаскированиеКириллицы Тогда
				
				Первый = Истина; Для Каждого Элемент Из Значение Цикл
					Ключ = Элемент.Ключ; Если ТипДопустимыхКлючей.СодержитТип(ТипЗнч(Ключ)) Тогда Ключ = jsonЗаписатьСтроку(Строка(Ключ), ПолноеМаскированиеСимволов, МаскированиеКириллицы); Иначе ВызватьИсключение ИсключениеНедопустимыйТипКлюча(Неопределено, Ключ); КонецЕсли;
					Если Первый Тогда
						Результат = ПереносСтроки + СледующееСмещение + Ключ + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
					Иначе
						Результат = Результат + "," + ПереносСтроки + СледующееСмещение + Ключ + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
					КонецЕсли;
				КонецЦикла;
				
			Иначе
			
				Первый = Истина; Для Каждого Элемент Из Значение Цикл
					Ключ = Элемент.Ключ; Тип = ТипЗнч(Ключ); Если (Тип = Тип("Строка")) Тогда Ключ = jsonЗаписатьСтроку(Ключ, ПолноеМаскированиеСимволов, МаскированиеКириллицы); ИначеЕсли ТипДопустимыхКлючей.СодержитТип(Тип) Тогда Ключ = """" + Ключ + """"; Иначе ВызватьИсключение ИсключениеНедопустимыйТипКлюча(Неопределено, Ключ); КонецЕсли;
					Если Первый Тогда
						Результат = ПереносСтроки + СледующееСмещение + Ключ + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
					Иначе
						Результат = Результат + "," + ПереносСтроки + СледующееСмещение + Ключ + ":" + Отступ + jsonЗаписать(Элемент.Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
					КонецЕсли;
				КонецЦикла;
				
			КонецЕсли;
			Возврат "{" + Результат + ПереносСтроки + Смещение + "}";
			
		Иначе
			
			// Пустое соответсвие.
			Возврат "{}";
		
		КонецЕсли;
	КонецЕсли;
	
	// Массивы.
	Если ВспомогательныеДанные.Массивы.СодержитТип(Тип) Тогда
		Если Значение.Количество() Тогда
						
			// форматирование.
			СледующееСмещение = Смещение + Табуляция;

			Первый = Истина; Для Каждого Элемент Из Значение Цикл
				Если Первый Тогда
					Результат = ПереносСтроки + СледующееСмещение + jsonЗаписать(Элемент, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
				Иначе
					Результат = Результат + "," + ПереносСтроки + СледующееСмещение + jsonЗаписать(Элемент, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
				КонецЕсли;
			КонецЦикла;
		
			Возврат "[" + Результат + ПереносСтроки + Смещение + "]";
		
		Иначе
			
			// Пустой массив.
			Возврат "[]";
		
		КонецЕсли;
	КонецЕсли;
	
	// Список значений.
	Если (Тип = Тип("СписокЗначений")) Тогда
		Если Значение.Количество() Тогда
						
			// форматирование.
			СледующееСмещение = Смещение + Табуляция;

			Структура = Новый Структура("Значение,Представление,Пометка");
			Первый = Истина; Для Каждого Элемент Из Значение Цикл
				ЗаполнитьЗначенияСвойств(Структура, Элемент);
				Если Первый Тогда
					Результат = ПереносСтроки + СледующееСмещение + jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
				Иначе
					Результат = Результат + "," + ПереносСтроки + СледующееСмещение + jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
				КонецЕсли;
			КонецЦикла;
			
			Возврат "[" + Результат + ПереносСтроки + Смещение + "]";
		
		Иначе
			
			// Пустой список значений.
			Возврат "[]";
		
		КонецЕсли;
	КонецЕсли;
	
	// Таблица значений.
	#Если ВебКлиент Или ТонкийКлиент Тогда
	#Иначе
	Если (Тип = Тип("ТаблицаЗначений")) Тогда
		Если Значение.Количество() Тогда
						
			// форматирование.
			СледующееСмещение = Смещение + Табуляция;
	
			Структура = Новый Структура; НаборКолонок = Значение.Колонки; Для Каждого Колонка Из НаборКолонок Цикл Структура.Вставить(Колонка.Имя); КонецЦикла;
			
			Первый = Истина; Для Каждого Элемент Из Значение Цикл
				ЗаполнитьЗначенияСвойств(Структура, Элемент);
				Если Первый Тогда
					Результат = ПереносСтроки + СледующееСмещение + jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
				Иначе
					Результат = Результат + "," + ПереносСтроки + СледующееСмещение + jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
				КонецЕсли;
			КонецЦикла;
			Возврат "[" + Результат + ПереносСтроки + Смещение + "]";
				
		Иначе
			
			// Пустая таблица значений.
			Возврат "[]";
		
		КонецЕсли;
	КонецЕсли;
	
	// Коллекция строк дерева значений.
	Если (Тип = Тип("КоллекцияСтрокДереваЗначений")) Тогда
		Если Значение.Количество() Тогда
						
			// форматирование.
			СледующееСмещение = Смещение + Табуляция;
	
			Структура = Колонки; Первый = Истина; Для Каждого Элемент Из Значение Цикл
				ЗаполнитьЗначенияСвойств(Структура, Элемент); Структура.Строки = Элемент.Строки;
				Если Первый Тогда
					Результат = ПереносСтроки + СледующееСмещение + jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Первый = Ложь;
				Иначе
					Результат = Результат + "," + ПереносСтроки + СледующееСмещение + jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Колонки, СледующееСмещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
				КонецЕсли;
			КонецЦикла;
			Возврат "[" + Результат + ПереносСтроки + Смещение + "]";
		
		Иначе
			
			// Пустая коллекция строк.
			Возврат "[]";
		
		КонецЕсли;
	КонецЕсли;
	
	// Дерево значений.
	Если (Тип = Тип("ДеревоЗначений")) Тогда
		
		Структура = Новый Структура("Строки"); НаборКолонок = Значение.Колонки; Для Каждого Колонка Из НаборКолонок Цикл Структура.Вставить(Колонка.Имя); КонецЦикла;
		Возврат jsonЗаписать(Значение.Строки, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Структура, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
		
	КонецЕсли;
	
	// Запрос.
	Если (Тип = Тип("Запрос")) Тогда Попытка Возврат jsonЗаписать(Значение.Выполнить().Выгрузить(), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); Исключение ВызватьИсключение ИсключениеНевозможноВыполнитьЗапрос(ИнформацияОбОшибке().Причина.Описание); КонецПопытки; КонецЕсли;
	
	// Результат запроса.
	Если (Тип = Тип("РезультатЗапроса")) Тогда Возврат jsonЗаписать(Значение.Выгрузить(), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	
	// Выборка из результата запроса.
	Если (Тип = Тип("ВыборкаИзРезультатаЗапроса")) Тогда
		
		Структура = Новый Структура; НаборКолонок = Значение.Владелец().Колонки; Для Каждого Колонка Из НаборКолонок Цикл Структура.Вставить(Колонка.Имя); КонецЦикла;
		ЗаполнитьЗначенияСвойств(Структура, Значение);
		Возврат jsonЗаписать(Структура, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
		
	КонецЕсли;
	
	// Построители.
	Если ВспомогательныеДанные.Построители.СодержитТип(Тип) Тогда Попытка Значение.Выполнить(); Исключение ВызватьИсключение ИсключениеНевозможноВыполнитьЗапрос(ИнформацияОбОшибке().Причина.Описание); КонецПопытки; Возврат jsonЗаписать(Значение.Результат, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	
	// Хранилище значения.
	Если (Тип = Тип("ХранилищеЗначения")) Тогда Возврат jsonЗаписать(Значение.Получить(), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	#КонецЕсли
	
	// Двоичные данные.
	Если (Тип = Тип("ДвоичныеДанные")) Тогда
		#Если ВебКлиент Или ТонкийКлиент Тогда
		Возврат """" + СтрЗаменить(СтрЗаменить(СтрЗаменить(Base64Строка(Значение), Символы.ВК, ""), Символы.ПС, ""), "/", "\/") + """";
		#Иначе
		Возврат """" + СтрЗаменить(СтрЗаменить(СтрЗаменить(XMLСтрока(Значение), Символы.ВК, ""), Символы.ПС, ""), "/", "\/") + """";
		#КонецЕсли
	КонецЕсли;
	
	// Картинка.
	Если (Тип = Тип("Картинка")) Тогда
		#Если ВебКлиент Или ТонкийКлиент Тогда
		Возврат """" + СтрЗаменить(СтрЗаменить(СтрЗаменить(Base64Строка(Значение.ПолучитьДвоичныеДанные()), Символы.ВК, ""), Символы.ПС, ""), "/", "\/") + """";
		#Иначе
		Возврат """" + СтрЗаменить(СтрЗаменить(СтрЗаменить(XMLСтрока(Значение.ПолучитьДвоичныеДанные()), Символы.ВК, ""), Символы.ПС, ""), "/", "\/") + """";
		#КонецЕсли
	КонецЕсли;
	
	// Ключ и значение.
	Если (Тип = Тип("КлючИЗначение")) Тогда Возврат jsonЗаписать(Новый Структура("Ключ,Значение", Значение.Ключ, Значение.Значение), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	
	// Клиентские типы.
	#Если НаСервере Тогда
	Если ВспомогательныеДанные.КлиентскиеТипы.СодержитТип(Тип) Тогда
		Если (Тип = Тип("ДанныеФормыДерево")) Тогда
			Возврат jsonЗаписать(ДанныеФормыВЗначение(Значение, Тип("ДеревоЗначений")), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
		Иначе
			Возврат jsonЗаписать(Значение.Выгрузить(), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
		КонецЕсли;
	КонецЕсли;
	#КонецЕсли
	
	// COMSafeArray.
	#Если ВебКлиент Тогда
	#Иначе
	Если (Тип = Тип("COMSafeArray")) Тогда Возврат jsonЗаписать(Значение.Выгрузить(), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	#КонецЕсли
			
	// Ссылки.
	#Если ВебКлиент Или ТонкийКлиент Тогда
	#Иначе
	Перечисление = Перечисления.ТипВсеСсылки().СодержитТип(Тип);
	Если Перечисление Или
		 Справочники.ТипВсеСсылки().СодержитТип(Тип) Или
		 Документы.ТипВсеСсылки().СодержитТип(Тип) Или
		 ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Или
		 ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Или
		 ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Или
		 Задачи.ТипВсеСсылки().СодержитТип(Тип) Или
		 БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Или
		 БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(Тип) Или
		 ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Тогда 
		Возврат jsonЗаписатьСсылку(Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Перечисление, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы);
	КонецЕсли;
	#КонецЕсли
	
	// Неподдерживаемые типы.
	Возврат jsonЗаписатьСтроку(Значение, ПолноеМаскированиеСимволов, МаскированиеКириллицы);

КонецФункции // jsonЗаписать()

Функция jsonЗаписатьСтроку(Значение, ПолноеМаскированиеСимволов, МаскированиеКириллицы)
	
	// Маскирование служебных символов.
	Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Значение, 
						"\",			"\\"),			// x5c
						"/",			"\/"),			// x2f
						Символ(008),	"\b"),			// x08
						Символы.Таб,	"\t"), 			// x09
						Символы.ПС,		"\n"),			// x0a
						Символы.ПФ,		"\f"),			// x0c
						Символы.ВК,		"\r"),			// x0d
						"""",			"\""");			// x22

	// Маскирование специальных символов.
	Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
						Символ(00),		"\u0000"),
						Символ(01),		"\u0001"),
						Символ(02),		"\u0002"),
						Символ(03),		"\u0003"),
						Символ(04),		"\u0004"),
						Символ(05),		"\u0005"),
						Символ(06),		"\u0006"),
						Символ(07),		"\u0007"),
						Символ(11),		"\u000b"),
						Символ(14),		"\u000e"),
						Символ(15),		"\u000f"),
						Символ(16),		"\u0010"),
						Символ(17),		"\u0011"),
						Символ(18),		"\u0012"),
						Символ(19),		"\u0013"),
						Символ(20),		"\u0014"),
						Символ(21),		"\u0015"),
						Символ(22),		"\u0016"),
						Символ(23),		"\u0017"),
						Символ(24),		"\u0018"),
						Символ(25),		"\u0019"),
						Символ(26),		"\u001a"),
						Символ(27),		"\u001b"),
						Символ(28),		"\u001c"),
						Символ(29),		"\u001d"),
						Символ(30),		"\u001e"),
						Символ(31),		"\u001f");
						
	Если ПолноеМаскированиеСимволов Тогда
							
		// Маскирование сиволов обрабатываемых JavaScript-ом не правильно.
		Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
						Символ(127),	"\u007f"),
						Символ(128),	"\u0080"),
						Символ(129),	"\u0081"),
						Символ(130),	"\u0082"),
						Символ(131),	"\u0083"),
						Символ(132),	"\u0084"),
						Символ(133),	"\u0085"),
						Символ(134),	"\u0086"),
						Символ(135),	"\u0087"),
						Символ(136),	"\u0088"),
						Символ(137),	"\u0089"),
						Символ(138),	"\u008a"),
						Символ(139),	"\u008b"),
						Символ(140),	"\u008c"),
						Символ(141),	"\u008d"),
						Символ(142),	"\u008e"),
						Символ(143),	"\u008f"),
						Символ(144),	"\u0090"),
						Символ(145),	"\u0091"),
						Символ(146),	"\u0092"),
						Символ(147),	"\u0093"),
						Символ(148),	"\u0094"),
						Символ(149),	"\u0095"),
						Символ(150),	"\u0096"),
						Символ(151),	"\u0097"),
						Символ(152),	"\u0098"),
						Символ(153),	"\u0099"),
						Символ(154),	"\u009a"),
						Символ(155),	"\u009b"),
						Символ(156),	"\u009c"),
						Символ(157),	"\u009d"),
						Символ(158),	"\u009e"),
						Символ(159),	"\u009f"),
						Символ(173),	"\u00ad");
						
		Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
						Символ(1536),	"\u0600"),
						Символ(1537),	"\u0601"),
						Символ(1538),	"\u0602"),
						Символ(1539),	"\u0603"),
						Символ(1540),	"\u0604"),
						Символ(1807),	"\u070f"),
						Символ(6068),	"\u17b4"),
						Символ(6069),	"\u17b5"),
						Символ(8204),	"\u200c"),
						Символ(8205),	"\u200d"),
						Символ(8206),	"\u200e"),
						Символ(8207),	"\u200f"),
						Символ(8232),	"\u2028"),
						Символ(8233),	"\u2029"),
						Символ(8234),	"\u202a"),
						Символ(8235),	"\u202b"),
						Символ(8236),	"\u202c"),
						Символ(8237),	"\u202d"),
						Символ(8238),	"\u202e"),
						Символ(8239),	"\u202f"),
						Символ(8288),	"\u2060"),
						Символ(8289),	"\u2061"),
						Символ(8290),	"\u2062"),
						Символ(8291),	"\u2063"),
						Символ(8292),	"\u2064"),
						Символ(8293),	"\u2065"),
						Символ(8294),	"\u2066"),
						Символ(8295),	"\u2067");
						
		Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
						Символ(8296),	"\u2068"),
						Символ(8297),	"\u2069"),
						Символ(8268),	"\u206a"),
						Символ(8299),	"\u206b"),
						Символ(8300),	"\u206c"),
						Символ(8301),	"\u206d"),
						Символ(8302),	"\u206e"),
						Символ(8303),	"\u206f"),
						Символ(65279),	"\ufeff"),
						Символ(65520),	"\ufff0"),
						Символ(65521),	"\ufff1"),
						Символ(65522),	"\ufff2"),
						Символ(65523),	"\ufff3"),
						Символ(65524),	"\ufff4"),
						Символ(65525),	"\ufff5"),
						Символ(65526),	"\ufff6"),
						Символ(65527),	"\ufff7"),
						Символ(65528),	"\ufff8"),
						Символ(65529),	"\ufff9"),
						Символ(65530),	"\ufffa"),
						Символ(65531),	"\ufffb"),
						Символ(65532),	"\ufffc"),
						Символ(65533),	"\ufffd"),
						Символ(65534),	"\ufffe"),
						Символ(65535),	"\uffff");
	
	КонецЕсли;
					
	Если МаскированиеКириллицы Тогда
		
		// Маскирование кириллических символов.
		Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
                        "А",            "\u0410"),
                        "Б",            "\u0411"),
                        "В",            "\u0412"),
                        "Г",            "\u0413"),
                        "Д",            "\u0414"),
                        "Е",            "\u0415"),
                        "Ж",            "\u0416"),
                        "З",            "\u0417"),
                        "И",            "\u0418"),
                        "Й",            "\u0419"),
                        "К",            "\u041a"),
                        "Л",            "\u041b"),
                        "М",            "\u041c"),
                        "Н",            "\u041d"),
                        "О",            "\u041e"),
                        "П",            "\u041f"),
                        "Р",            "\u0420"),
                        "С",            "\u0421"),
                        "Т",            "\u0422"),
                        "У",            "\u0423"),
                        "Ф",            "\u0424"),
                        "Х",            "\u0425"),
                        "Ц",            "\u0426"),
                        "Ч",            "\u0427"),
                        "Ш",            "\u0428"),
                        "Щ",            "\u0429"),
                        "Ъ",            "\u042a"),
                        "Ы",            "\u042b"),
                        "Ь",            "\u042c"),
                        "Э",            "\u042d"),
                        "Ю",            "\u042e"),
                        "Я",            "\u042f");
						
		Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
						"а",            "\u0430"),
						"б",            "\u0431"),
						"в",            "\u0432"),
						"г",            "\u0433"),
						"д",            "\u0434"),
						"е",            "\u0435"),
						"ж",            "\u0436"),
						"з",            "\u0437"),
						"и",            "\u0438"),
						"й",            "\u0439"),
						"к",            "\u043a"),
						"л",            "\u043b"),
						"м",            "\u043c"),
						"н",            "\u043d"),
						"о",            "\u043e"),
						"п",            "\u043f"),
						"р",            "\u0440"),
						"с",            "\u0441"),
						"т",            "\u0442"),
						"у",            "\u0443"),
						"ф",            "\u0444"),
						"х",            "\u0445"),
						"ц",            "\u0446"),
						"ч",            "\u0447"),
						"ш",            "\u0448"),
						"щ",            "\u0449"),
						"ъ",            "\u044a"),
						"ы",            "\u044b"),
						"ь",            "\u044c"),
						"э",            "\u044d"),
						"ю",            "\u044e"),
						"я",            "\u044f");
						
		Результат = СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(СтрЗаменить(Результат, 
						"’",            "\u2019"),
						"Ґ",            "\u0490"),
						"Ђ",            "\u0402"),
						"Ѓ",            "\u0403"),
						"Ѐ",            "\u0400"),
						"Ё",            "\u0401"),
						"Є",            "\u0404"),
						"Ѕ",            "\u0405"),
						"Ѝ",            "\u040d"),
						"І",            "\u0406"),
						"Ї",            "\u0407"),
						"Ј",            "\u0408"),
						"Љ",            "\u0409"),
						"Њ",            "\u040a"),
						"Ћ",            "\u040b"),
						"Ќ",            "\u040c"),
						"Ў",            "\u040e"),
						"Џ",            "\u040f"),
						"ґ",            "\u0491"),
						"ђ",            "\u0452"),
						"ѓ",            "\u0453"),
						"ѐ",            "\u0450"),
						"ё",            "\u0451"),
						"є",            "\u0454"),
						"ѕ",            "\u0455"),
						"ѝ",            "\u045d"),
						"і",            "\u0456"),
						"ї",            "\u0457"),
						"ј",            "\u0458"),
						"љ",            "\u0459"),
						"њ",            "\u045a"),
						"ћ",            "\u045b"),
						"ќ",            "\u045c"),
						"ў",            "\u045e"),
						"џ",            "\u045f");						
						
	КонецЕсли;
	
	// Кавычки.
	Возврат """" + Результат + """";
	
КонецФункции // jsonЗаписатьСтроку()

Функция jsonЗаписатьСсылку(Значение, Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Перечисление, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы)
#Если ВебКлиент Или ТонкийКлиент Тогда
#Иначе
	
	// Идентификатор.
	Если Стандарт Тогда 
		Если Перечисление Тогда Идентификатор = Лев(Прав(ЗначениеВСтрокуВнутр(Значение), 33), 32); Идентификатор = Прав(Идентификатор, 8) + "-" + Сред(Идентификатор, 21, 4) + "-" + Сред(Идентификатор, 17, 4) + "-" + Лев(Идентификатор, 4) + "-" + Сред(Идентификатор, 5, 12); Иначе Идентификатор = XMLСтрока(Значение); КонецЕсли;
	Иначе 
		Идентификатор = ЗначениеВСтрокуВнутр(Значение); Идентификатор = "¦ref¦" + СтрЗаменить(СтрЗаменить(Сред(Идентификатор, 6, СтрДлина(Идентификатор) - 6), ":", "×"), ",", "÷") + "¦";
	КонецЕсли;
	
	// Включая представление ссылки.
	Если ПредставленияСсылок Тогда Возврат jsonЗаписать(Новый Структура("Ссылка,Представление", Идентификатор, Строка(Значение)), Стандарт, ПредставленияСсылок, ВспомогательныеДанные, Неопределено, Смещение, Отступ, Табуляция, ПереносСтроки, ПолноеМаскированиеСимволов, МаскированиеКириллицы); КонецЕсли;
	
	// Ссылка.
	Возврат """" + Идентификатор + """";
	
#КонецЕсли
КонецФункции // jsonЗаписатьСсылку()


// ─────────────────────────────────────────────────────────────────────────────
//  ЛОКАЛИЗАЦИЯ

Функция СформироватьСтрокуПоШаблону(Строка, Параметры)
	
	Результат = Строка;
		
	Для Каждого Параметр Из Параметры Цикл
		Результат = СтрЗаменить(Результат, "[" + Параметр.Ключ + "]", Строка(Параметр.Значение));
	КонецЦикла;

	Возврат Результат;
	
КонецФункции // СформироватьСтрокуПоШаблону()


Функция ИсключениеПустойПакетДанных()
	
	Возврат НСтр("ru = 'JSON: Пустой пакет данных.'; uk = 'JSON: Порожній пакет даних.'");

КонецФункции // ИсключениеНеожиданноеОкончаниеСтроки()

Функция ИсключениеНекорректныйПакетДанных(Индекс)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный пакет данных в позиции [Индекс].'; uk = 'JSON: Некоректний пакет даних у позиції [Индекс].'"),
		Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНекорректныйПакетДанных()

Функция ИсключениеНеожиданноеОкончаниеПакетаДанных()
	
	Возврат НСтр("ru = 'JSON: Неожиданное окончание пакета данных.'; uk = 'JSON: Несподіване закінчення пакета даних.'");

КонецФункции // ИсключениеНеожиданноеОкончаниеПакетаДанных()

Функция ИсключениеНеожиданноеОкончаниеМассива(Индекс)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Неожиданное окончание массива в позиции [Индекс].'; uk = 'JSON: Несподіване закінчення масиву у позиції [Индекс].'"),
		Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНеожиданноеОкончаниеМассива()

Функция ИсключениеНеожиданноеОкончаниеОбъетка(Индекс)

	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Неожиданное окончание объекта в позиции [Индекс].'; uk = 'JSON: Несподіване закінчення об''єкту у позиції [Индекс].'"),
	   Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНеожиданноеОкончаниеОбъетка()

Функция ИсключениеНекорректныйТипNull(Индекс)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный тип Null в позиции [Индекс].'; uk = 'JSON: Некоректний тип Null у позиції [Индекс].'"),
	   Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНекорректныйТипNull()

Функция ИсключениеНекорректныйТипБулево(Индекс)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный тип Булево в позиции [Индекс].'; uk = 'JSON: Некоректний тип Булево у позиції [Индекс].'"),
	   Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНекорректныйТипБулево()

Функция ИсключениеНекорректныйТипНеопределено(Индекс)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный тип Неопределено в позиции [Индекс].'; uk = 'JSON: Некоректний тип Невизначено у позиції [Индекс].'"),
		Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНекорректныйТипНеопределено()

Функция ИсключениеНекорректныйФорматСтроки(Индекс)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный формат строки в позиции [Индекс].'; uk = 'JSON: Некоректний формат рядка у позиції [Индекс].'"),
		Новый Структура("Индекс", Индекс));

КонецФункции // ИсключениеНекорректныйФорматСтроки()

Функция ИсключениеНекорректныйФорматДаты(Индекс, Значение)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный формат даты [Значение] в позиции [Индекс].'; uk = 'JSON: Некоректний формат дати [Значение] у позиції [Индекс].'"),
		Новый Структура("Индекс", Индекс, Символ(034) + Значение + Символ(034)));

КонецФункции // ИсключениеНекорректныйФорматДаты()

Функция ИсключениеНекорректныйФорматЧисла(Индекс, Значение)
	
	Если ПустаяСтрока(Значение) Тогда
		
		Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Неверный формат данных в позиции [Индекс].'; uk = 'JSON: Невірний формат даних у позиції [Индекс].'"),
			Новый Структура("Индекс", Индекс));

	Иначе
		
		Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Некорректный формат числа [Значение] в позиции [Индекс].'; uk = 'JSON: Некоректний формат числа [Значение] у позиції [Индекс].'"),
			Новый Структура("Индекс,Значение", Индекс, Символ(034) + Значение + Символ(034)));
					   
	КонецЕсли;
					   
КонецФункции // ИсключениеНекорректныйФорматЧисла()

Функция ИсключениеНедопустимыйСимвол(Индекс, Символ)
	
	Если (Символ = Неопределено) Тогда
		
		Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Недопустимый символ в позиции [Индекс].'; uk = 'JSON: Неприпустимий символ в позиції [Индекс].'"),
			Новый Структура("Индекс", Индекс));

	Иначе
		
		Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Недопустимый символ в позиции [Индекс], ожидается [Символ].'; uk = 'JSON: Неприпустимий символ в позиції [Индекс], очікується [Символ].'"),
			Новый Структура("Индекс,Символ", Индекс, Символ(034) + Символ + Символ(034)));

	КонецЕсли;
				   
КонецФункции // ИсключениеНедопустимыйСимвол()

Функция ИсключениеНеопознанныйТип(Индекс, Тип)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Недопустимый тип [Тип] в позиции [Индекс].'; uk = 'JSON: Неприпустимий тип [Тип] у позиції [Индекс].'"),
		Новый Структура("Индекс,Тип", Индекс, Символ(034) + Тип + Символ(034)));

КонецФункции // ИсключениеНеопознанныйТип()

Функция ИсключениеНевозможноПреобразоватьЗначение(Индекс, Значение)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Невозможно преобразовать значение [Значение] в позиции [Индекс].'; uk = 'JSON: Неможливо перетворити значення [Значение] у позиції [Индекс].'"),
		Новый Структура("Индекс,Значение", Индекс, Символ(034) + Значение + Символ(034)));

КонецФункции // ИсключениеНевозможноПреобразоватьЗначение()

Функция ИсключениеНевозможноПреобразоватьЗначениеНаКлиенте(Индекс, Значение)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Невозможно на клиенте преобразовать значение [Значение] в позиции [Индекс].'; uk = 'JSON: Неможливо на клієнті перетворити значення [Значение] у позиції [Индекс].'"),
		Новый Структура("Индекс,Значение", Индекс, Символ(034) + Значение + Символ(034)));

КонецФункции // ИсключениеНевозможноПреобразоватьЗначениеНаКлиенте()


Функция ИсключениеНекорректныйПараметр(Параметр)
	
	Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Недопустимое значение параметра [Параметр].'; uk = 'JSON: Неприпустиме значення параметра [Параметр].'"),
		Новый Структура("Параметр", Символ(034) + Параметр + Символ(034)));

КонецФункции // ИсключениеНекорректныйПараметр()


Функция ИсключениеНедопустимыйТипКлюча(Индекс, Значение)
	
	Если (Индекс = Неопределено) Тогда
		
		Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Недопустимый тип значения ключа [Тип].'; uk = 'JSON: Неприпустимий тип значення ключа [Тип].'"),
			Новый Структура("Тип", ТипЗнч(Значение)));

	Иначе
		
		Возврат СформироватьСтрокуПоШаблону(НСтр("ru = 'JSON: Недопустимый тип значения ключа [Тип] в позиции [Индекс].'; uk = 'JSON: Неприпустимий тип значення ключа [Тип] в позиції [Индекс].'"),
			Новый Структура("Индекс,Тип", Индекс, Символ(034) + ТипЗнч(Значение) + Символ(034)));

	КонецЕсли;

КонецФункции // ИсключениеНедопустимыйТипКлюча()

Функция ИсключениеНевозможноВыполнитьЗапрос(Описание)
	
	Позиция = Найти(Описание, "}: "); Если Позиция Тогда Позиция = Позиция + 3; Иначе Позиция = 1; КонецЕсли;
	Длина = Найти(Описание, Символы.ПС); Если Длина Тогда Длина = Длина - Позиция; Иначе Длина = СтрДлина(Описание); КонецЕсли;
	Возврат НСтр("ru = 'JSON: Невозможно выполнить запрос. '; uk = 'JSON: Неможливо виконати запит. '") + Сред(Описание, Позиция, Длина) + ".";

КонецФункции // ИсключениеНевозможноВыполнитьЗапрос()

//}

#КонецОбласти




мПолныеПрава = Истина;

ЗагруженныеДанные = Новый Соответствие;

// Для конвертирования текста в формате Textile в HTML используется textile-js
// https://github.com/borgar/textile-js
// Copyright © 2012, Borgar Þorsteinsson (MIT License).
СкриптJS = ПолучитьИмяВременногоФайла("js");
Попытка
	ПолучитьМакет("textile_js").Записать(СкриптJS);
	мКонвертерTextileToHTML = СкриптJS; 
Исключение КонецПопытки;
