Имя: Пароль:
1C
1С v8
XDTO Десериализация справочника
0 Gera1t
 
19.03.25
16:09
Здравствуйте!
Есть 2 одинаковые базы, нужно из одной в другую загружать справочник Номенклатура.
В базе источнике сделал Web сервис, тип возвращаемых данных указал: CatalogObject.Номенклатура ( http://v8.1c.ru/8.1/data/enterprise/current-config )

данные передаю в виде массива, вот так:
    Ответ = Новый Массив;
    
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ
        |    Номенклатура.Ссылка КАК Ссылка
        |ИЗ
        |    Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |    НЕ Номенклатура.ПометкаУдаления";
    
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        Ответ.Добавить(ВыборкаДетальныеЗаписи.Ссылка);
    КонецЦикла;
    
    Возврат СериализаторXDTO.ЗаписатьXDTO(Ответ);

В базы приемнике получаю данные вот так:
    Определение = Новый WSОпределения("http://localhost/MM/ws/Nomenclature.1cws?wsdl  , Логин, Пароль);
    Прокси = Новый WSПрокси(Определение, "http://localhost/Nomenclature", "Nomenclature", "NomenclatureSoap");      
    Прокси.Пользователь = Логин;
    Прокси.Пароль = Пароль;      
            
    Данные = Прокси.GetData();
    
    СписокНоменклатуры = СериализаторXDTO.ПрочитатьXDTO(Данные);

В переменной Данные с типом СписокXDTO.
Но при попытке СериализаторXDTO.ПрочитатьXDTO(Данные) получаю ошибку
Ошибка отображения типов:
Отсутствует отображение для типа '{http://v8.1c.ru/8.1/data/enterprise/current-config}CatalogRef.Номенклатура'

Подскажите пожалуйста как десериализовать XDTO?
1 Gera1t
 
19.03.25
16:36
Если я передаю не Массив, а ссылку на один элемент номенклатуры, то как будто десериализация происходит автоматически, я сразу получаю ссылку. Но если это вновь созданный элемент справочника, то получаю Объект не найден
2 Галахад
 
гуру
19.03.25
16:45
Скорее всего косяк в коде.
3 Gera1t
 
19.03.25
16:47
И исходя из (1) подскажите пожалуйста, как правильно создавать недостающий элемент справочника?
4 Gera1t
 
19.03.25
16:48
В Данные.Value я вижу список передаваемой номенклатуры и могу перебрать его
5 Gera1t
 
19.03.25
16:53
Т.е. резюмируя все вышесказанное, вот это СериализаторXDTO.ПрочитатьXDTO(Данные) делать не нужно, в Данные.Value уже список с ссылками на элементы справочника Номенклатура.
Но если передается новый элемент, которого нет в базе приемнике, то я получаю Объект не найден и не очень понимаю как в этом случае создать новый элемент
6 Gera1t
 
19.03.25
16:55
Ну и если элемент справочника был переименован, по ссылке я вижу название, которое было в базе приемнике, и не вижу как он называется в базе источнике
7 Мультук
 
гуру
19.03.25
17:07
(0)

Добавим в ваш код немного волшебства для простоты отладки (см ниже)
В результате получаем

<ляля xmlns="http://v8.1c.ru/8.1/data/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Value xmlns:d2p1="http://v8.1c.ru/8.1/data/enterprise/current-config" xsi:type="d2p1:CatalogRef.Номенклатура">5e5a7257-6896-11e8-8780-b06ebf2faaf6</Value>
    <Value xmlns:d2p1="http://v8.1c.ru/8.1/data/enterprise/current-config" xsi:type="d2p1:CatalogRef.Номенклатура">c3314ae7-6899-11e8-8780-b06ebf2faaf6</Value>
</ляля>


Возникает вопрос. А где же код, Наименование, и прочие реквизиты объекта "Номенклатура" ?

Но если код немного поменять

Ответ.Добавить(ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект());


То и XML-файл в переменной "Стр" становится намного веселее.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

 	Ответ = Новый Массив;
    
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ ПЕРВЫЕ 2
        |	Номенклатура.Ссылка КАК Ссылка
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	НЕ Номенклатура.ПометкаУдаления
        |	И Номенклатура.ЭтоГруппа = ЛОЖЬ
		|";
    
    РезультатЗапроса = Запрос.Выполнить();
    
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        Ответ.Добавить(ВыборкаДетальныеЗаписи.Ссылка);
    КонецЦикла;
    
    тт = СериализаторXDTO.ЗаписатьXDTO(Ответ); 	
	
	стр = ОбъектXDTOВСтрокуXML(тт, "ляля");
	
КонецПроцедуры


Функция ОбъектXDTOВСтрокуXML(ОбъектXDTO, ИмяКорневогоУзла, ЗаписатьОбъявлениеXML = Ложь) Экспорт
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку("UTF-8");
	Если ЗаписатьОбъявлениеXML Тогда
		ЗаписьXML.ЗаписатьОбъявлениеXML();
	КонецЕсли;
	ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO, ИмяКорневогоУзла);
	Возврат ЗаписьXML.Закрыть();
КонецФункции

8 Gera1t
 
20.03.25
09:32
(7) Большое спасибо! Ни разу не вникал в то, как работает сериализация, опыта в этой сфере нет
9 Gera1t
 
20.03.25
09:53
Я так и не понял до конца как мне прочитать данные переданные через web сервис.
Если бы я использовал HTTP-сервис, я бы сделал так:
передавал в json массив из структур, в приемнике считывал бы его.

При использовании WEB-сервиса: если я передаю CatalogObject.Номенклатура ( http://v8.1c.ru/8.1/data/enterprise/current-config ), то все отлично если нужно просто передать ссылку на объект из одной конфигурации в другую, но у меня задача получить создаваемые или измененные объекты и в базе приемнике переименовать или создать точно такие объекты

Если я передаю XML как строку, там я получаю кучу лишнего и читать XML, по-моему сложнее чем JSON.

Подскажите пожалуйста как и с каким типом данных передать данные из конфигурации источника и как прочитать, с учетом измененных и новых объектов, данные в базе приемнике?
10 Gera1t
 
20.03.25
15:35
Если вдруг кому то интересно, то сделал так:
Во первых тип возвращаемых данных указал: ValueStorage ( http://v8.1c.ru/8.1/data/core )

Затем в базе источнике:

	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Номенклатура.Код КАК Код,
		|	Номенклатура.Наименование КАК Наименование,
		|	Номенклатура.Ссылка КАК Ссылка,
		|	Номенклатура.КатегорияНоменклатуры КАК КатегорияНоменклатуры
		|ИЗ
		|	Справочник.Номенклатура КАК Номенклатура
		|ГДЕ
		|	НЕ Номенклатура.ПометкаУдаления";
	
	РезультатЗапроса = Запрос.Выполнить();
	Возврат Новый ХранилищеЗначения(РезультатЗапроса.Выгрузить());


В базе приемнике:
	Определение = Новый WSОпределения("http://localhost/MM/ws/Directories.1cws?wsdl  , Логин, Пароль);
	Прокси = Новый WSПрокси(Определение, "http://192.168.1.62/Directories  , "Directories", "DirectoriesSoap");	   
	Прокси.Пользователь = Логин;
	Прокси.Пароль = Пароль;	  
	
	Данные = Прокси.GetData();
	
	ТЗ= Данные.Получить();


В ТЗ получаю Таблицу значений как в базе источнике.
Если ТЗ.Ссылка = Объект не найден создаю новый элемент справочника с наименованием ТЗ.Наименование. Если элемент справочника есть, но ТЗ.Ссылка.Наименование <> ТЗ.Наименование, переименовываю.
11 Михаил Козлов
 
20.03.25
16:39
"Если ТЗ.Ссылка = Объект не найден создаю новый элемент справочника с наименованием ТЗ.Наименование."
На всякий случай установите у него ссылку по ГУИДу в источнике.
Удобно еще через конвертацию данных.
Если конфигурации одинаковые, можно через штатную обработку Выгрузка/Загрузка данных XML.
12 Gera1t
 
21.03.25
11:38
(11)     
НовЭл = Справочники.КатегорииНоменклатуры.СоздатьЭлемент();
НовЭл.УстановитьСсылкуНового(Ссылка);

Вот так делаю в конфигурации приемнике.
Ссылка это ссылка на объект из конфигурации источника
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн