29 недопустимый формат передаваемого файла json
Формат JSON легко читается. Пример текстового файла в формате JSON:
"ОсновнойПоставщик" : "c8d578e9-9f33-11eb-80ad-364b50b7ef2d"Как правило JSON используется для обмена данными в веб-приложениях. Однако его можно применять и для обмена данными между двумя базами 1С.
JSON может включать в себя следующие элементы:
- Объект
- Строка
- Число
- Литералы: true, false, null
- Массив
Объект
Значением может быть любой тип:
- Другой JSON-объект
- Массив
- Строка
- Число
- Литералы: true, false, null
В данном примере три ключа:
- ЭтоКлюч
- ЭтоТожеКлюч
- ЭтоВложенныйОбъект
Строка и число
Литералы
В качестве литералов могут использоваться:
Массив
Значения массива могут быть любого типа: строки, числа, литералы, объекты и даже другие массивы:
ЗаписатьJSON
Чтобы записать данные в формате JSON из 1с нужно:
- Создать программный объект ЗаписьJSON
- Вызвать у него метод ОткрытьФайл, передав параметром путь к файлу, куда будут записаны данные в формате JSON
- С помощью метода глобального контекста ЗаписатьJSON выполнить сериализацию. Параметрами нужно передать созданный объект ЗаписьJSON и сами данные
- Закрыть ЗаписьJSON методом Закрыть
Соответствие между типами 1С и типами JSON:
Тип 1С | Тип JSON |
---|---|
Строка | Строка |
Число | Число |
Булево | true или false |
Дата | Строка |
Неопределено | null |
Массив | JSON-массив |
Фиксированный массив | JSON-массив |
Структура | JSON-объект |
Фиксированная структура | JSON-объект |
Соответствие | JSON-объект |
Фиксированное соответствие | JSON-объект |
Ключ соответствия и фиксированного соответствия может быть только строковым.
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON ( ПереносСтрокJSON . Авто , Символы . Таб ) ; Запись . ОткрытьФайл ( "F:\test.json" , , , ПараметрыЗаписиJSON ) ; ФиксСтруктура = Новый ФиксированнаяСтруктура ( Структура ) ; ФиксСоответствие = Новый ФиксированноеСоответствие ( Соответствие ) ;В результате файл будет содержать следующие данные:
В коде была использована строка:
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON ( ПереносСтрокJSON . Авто , Символы . Таб ) ;Здесь указывается, что при записи JSON нужно использовать перенос строк (первый параметр) и символ табуляции как отступ для каждого элемента JSON (второй параметр). Это нужно чтобы файл с JSON был более читаемым. Если указать первым параметром ПереносСтрокJSON.Нет, то JSON будет записан в одну строку.
Запись массива как JSON-объект
По умолчанию массив сериализуется в JSON-массив. Но в метод ЗаписатьJSON третьим параметром можно передать настройки сериализации JSON, где указать, что массивы нужно записывать как объекты. Ключом будет индекс элемента массива.
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON ( ПереносСтрокJSON . Авто , Символы . Таб ) ; Запись . ОткрытьФайл ( "F:\test.json" , , , ПараметрыЗаписиJSON ) ; Настройки . СериализовыватьМассивыКакОбъекты = Истина;Сериализация таблицы значений в JSON
Таблица значений является одной из часто используемых коллекций в 1С, но для нее нет автоматической сериализации в JSON. Для сериализации можно преобразовать таблицу в массив структур, а массив сериализовать в JSON:
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON ( ПереносСтрокJSON . Авто , Символы . Таб ) ; Запись . ОткрытьФайл ( "F:\test.json" , , , ПараметрыЗаписиJSON ) ;ПрочитатьJSON
Для чтения JSON файла используется программный объект ЧтениеJSON и метод ПрочитатьJSON:
- Создается программный объект ЧтениеJSON
- Методом ОткрытьФайл выполняется открытие файла с JSON
- Методом глобального контекста ПрочитатьJSON выполняется десериализация JSON
- Объект ЧтениеJSON закрывается методом Закрыть
Десериализация из JSON в типы 1С выполняется по следующим правилам:
Тип JSON | Тип 1С |
---|---|
Число | Число |
Строка | Строка |
true | Истина |
false | Ложь |
null | Неопределено |
JSON-объект | Структура или соответствие |
JSON-массив | Массив |
В результате в переменной Данные будет структура со следующим содержимым:
Чтение JSON в соответствие
Сейчас все JSON-объекты были прочитаны в структуру. Даже те, которые изначально были сериализованы из соответствия. Однако, в отличии от структуры, в ключах JSON-объектов могут быть пробелы или другие символы, которые нельзя использовать в ключах структуры. Например, если бы соответствие было записано так:
Чтобы прочитать такой JSON нужно в метод ПрочитатьJSON передать вторым параметром Истина. Тогда чтение всех JSON-объектов будет выполнено в соответствие:
В результате в переменной Данные будет соответствие со следующим содержимым:
Сериализация даты в JSON
Формат даты
При сериализации в JSON дата записывается как строка. При чтении тоже будет прочитана как строка, что не совсем удобно. Чтобы свойство с датой было прочитано как дата нужно в методе ПрочитатьJSON третьим параметром указать список имен свойств, которые должны быть прочитаны как дата. А четвертым параметром указать формат даты, в котором дата была записана в JSON. По умолчанию платформа 1С пишет дату в JSON в формате ISO.
//через запятую нужно перечислить список имен свойств, которые будут прочитаны как дата Данные = ПрочитатьJSON ( ЧтениеJSON , , ИменаСвойствСДатой , ФорматДатыJSON . ISO ) ;В результате свойство Дата будет прочитано как дата:
Платформа 1С может записывать дату в JSON в трех форматах:
Формат ISO используется по умолчанию. Для записи в формате JavaScript или Microsoft нужно явно указать это. При этом форматы JavaScript и Microsoft могут быть записаны только в варианте даты UTC (универсальная дата).
Например, запись в формате JavaScript:
ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON ( ПереносСтрокJSON . Авто , Символы . Таб ) ; Запись . ОткрытьФайл ( "F:\test.json" , , , ПараметрыЗаписиJSON ) ; Данные . Вставить ( "СвойствоСДатой" , Дата ( 2021 , 6 , 3 , 15 , 0 , 0 ) ) ; //в настройках нужно указать формат даты и вариант записи даты НастройкиСериализацииJSON = Новый НастройкиСериализацииJSON ; НастройкиСериализацииJSON . ФорматСериализацииДаты = ФорматДатыJSON . JavaScript ; НастройкиСериализацииJSON . ВариантЗаписиДаты = ВариантЗаписиДатыJSON . УниверсальнаяДата ; ЗаписатьJSON ( Запись , Данные , НастройкиСериализацииJSON ) ;При чтении также нужно указать формат JavaScript:
//через запятую нужно перечислить список имен свойств, которые будут прочитаны как дата Данные = ПрочитатьJSON ( ЧтениеJSON , , ИменаСвойствСДатой , ФорматДатыJSON . JavaScript ) ;Для записи в формате Microsoft нужно указать ФорматСериализацииДаты = Microsoft:
НастройкиСериализацииJSON . ФорматСериализацииДаты = ФорматДатыJSON . Microsoft ;И то же самое при чтении JSON:
Данные = ПрочитатьJSON ( ЧтениеJSON , , ИменаСвойствСДатой , ФорматДатыJSON . Microsoft ) ;Для формата ISO дату можно записать в трех вариантах:
- Локальная дата (без часового пояса)
- Локальная дата со смещением (относительно UTC)
- UTC (универсальная дата)
Локальная дата со смещением:
НастройкиСериализацииJSON = Новый НастройкиСериализацииJSON ; НастройкиСериализацииJSON . ФорматСериализацииДаты = ФорматДатыJSON . ISO ; НастройкиСериализацииJSON . ВариантЗаписиДаты = ВариантЗаписиДатыJSON . ЛокальнаяДатаСоСмещением ; НастройкиСериализацииJSON = Новый НастройкиСериализацииJSON ; НастройкиСериализацииJSON . ФорматСериализацииДаты = ФорматДатыJSON . ISO ; НастройкиСериализацииJSON . ВариантЗаписиДаты = ВариантЗаписиДатыJSON . УниверсальнаяДата ;ПрочитатьДатуJSON
Другой способ чтения даты из JSON это использование метода ПрочитатьДатуJSON. Сначала читаем JSON методом ПрочитатьJSON, а свойства с типом дата дополнительно читаем методом ПрочитатьДатуJSON. Первым параметром передается строковое представление даты, вторым формат даты. Результатом выполнения функции будет значение с типом дата:
Дата = ПрочитатьДатуJSON ( Формат ( Данные . СвойствоСДатой , "ЧГ=0" ) , ФорматДатыJSON . ISO ) ;Функции преобразования и восстановления
Функция преобразования
Для возможности выгрузки данных прикладных типов 1С можно использовать функцию преобразования. Данная функция указывается в методе ЗаписатьJSON четвертым параметром. Она должна быть экспортной. Пятым параметром указывается где находится данная функция (если в этом же модуле, то нужно указать ЭтотОбъект). Шестым параметром можно указать произвольные дополнительные данные, которые будут переданы в функцию преобразования. Данная функция будет вызвана для тех типов, которые по умолчанию не сериализуются в JSON. Функция вызывается для всех свойств, включая вложенные свойства, а также для элементов массива.
Например, выгрузим контрагента, у которого в реквизите ДатаРегистрации содержится дата, в реквизите ОсновнойДоговор ссылка на справочник Договоры, а в табличной части список контактных лиц. Причем одно контактное лицо указано строкой, а второе ссылкой на справочник Контактные лица:
Здесь приведены ответы на некоторые распространенные вопросы о встроенной поддержке JSON в SQL Server.
Выходные данные FOR JSON и JSON
FOR JSON PATH или FOR JSON AUTO?
Вопрос. Мне нужно создать текстовый результат JSON из простого SQL-запроса для одной таблицы. Выходные данные для FOR JSON PATH и FOR JSON AUTO совпадают. Какой из этих вариантов следует использовать?
Ответ. Используйте FOR JSON PATH. Несмотря на отсутствие различий в выходных данных JSON, режим AUTO применяет дополнительную логику, определяющую потребность во вложенных столбцах. Рассматривайте PATH как параметр по умолчанию.
Создание вложенной структуры JSON
Вопрос. Мне нужно создать сложную JSON с несколькими массивами на одном уровне. FOR JSON PATH может создавать вложенные объекты с использованием путей, а FOR JSON AUTO создает дополнительный уровень вложенности для каждой таблицы. Ни один из этих параметров не позволяет мне получить нужный результат. Как создать настраиваемый формат JSON, который напрямую не поддерживается существующими параметрами?
Ответ. Любую структуру данных можно создать, добавив запросы FOR JSON в качестве выражений столбца, возвращающих текст JSON. Кроме того, JSON можно создать вручную с помощью функции JSON_QUERY. Применение этих функции показано в приведенном ниже примере.
Каждый результат запроса FOR JSON или функции JSON_QUERY в выражениях столбца форматируется в виде отдельного вложенного подчиненного объекта JSON и включается в основной результат.
Предотвращение появления дважды экранированного JSON в выходных данных FOR JSON
Вопрос. Имеется текст JSON, хранящийся в столбце таблицы. Я хочу включить его в выходные данные FOR JSON. При этом FOR JSON экранирует все символы в JSON, поэтому я получаю строку JSON вместо вложенного объекта, как показано в следующем примере.
Этот запрос получает следующие выходные данные.
Как можно избежать этого? Я хочу, чтобы возвращался в виде объекта JSON, а не escape-текста.
Ответ. JSON, хранящийся в столбце текста или литерале, обрабатывается как обычный текст. В связи с этим он заключается в двойные кавычки и экранируется. Если вам нужно возвратить неэкранированный объект JSON, следует передать столбец JSON как аргумент функции JSON_QUERY, как показано в следующем примере.
JSON_QUERY без второго необязательного параметра возвращает в качестве результата только первый аргумент. Так как JSON_QUERY всегда возвращает правильный объект JSON, FOR JSON определяет, что экранировать этот результат не нужно.
JSON, созданная с помощью предложения WITHOUT_ARRAY_WRAPPER, экранируется в выходных данных FOR JSON
Вопрос. Я пытаюсь отформатировать выражение столбца с помощью FOR JSON и параметра WITHOUT_ARRAY_WRAPPER.
Похоже, что текст, возвращаемый запросом FOR JSON, экранируется как обычный текст. Это происходит только в том случае, если указан WITHOUT_ARRAY_WRAPPER. Почему он не рассматривается в качестве объекта JSON и не включается в результат неэкранированным?
Ответ. Если параметр WITHOUT_ARRAY_WRAPPER указан во внутреннем FOR JSON , создаваемый текст JSON может оказаться недопустимым объектом JSON. Поэтому внешний FOR JSON предполагает, что это обычный текст, и экранирует строку. Если вы уверены, что выходные данные JSON допустимы, заключите их в оболочку с помощью функции JSON_QUERY , чтобы превратить в правильно отформатированную JSON, как показано в следующем примере.
Возвращение вложенного подчиненного объекта JSON из текста JSON с помощью OPENJSON
Вопрос. Не удается открыть массив cоставных объектов JSON, содержащий скалярные значения, объекты и массивы, с помощью OPENJSON с явной схемой. Когда я ссылаюсь на ключ в предложении WITH, возвращаются только скалярные значения. Объекты и массивы возвращаются в виде значений NULL. Как извлекать объекты или массивы в качестве объектов JSON?
Ответ. Если требуется возвратить объект или массив в виде столбца, используйте параметр AS JSON в определении столбца, как показано в следующем примере.
Вместо JSON_VALUE возвращается длинное текстовое значение с параметром OPENJSON.
Вопрос. В тексте JSON имеется ключ описания, содержащий длинный текст. JSON_VALUE(@json, '$.description') возвращает NULL, а не значение.
Ответ. JSON_VALUE предназначена для возврата небольших скалярных значений. Обычно эта функция возвращает значение NULL вместо ошибки переполнения. Если требуется возвратить более длинные значения, используйте OPENJSON, поддерживающую значения NVARCHAR(MAX), как показано в следующем примере.
Для обработки повторяющихся ключей вместо JSON_VALUE используйте параметр OPENJSON.
Вопрос. В тексте JSON есть повторяющиеся ключи. JSON_VALUE возвращает только первый ключ, найденный в пути. Как возвратить все ключи с одинаковыми именами?
Ответ. Встроенные скалярные функции JSON возвращают только первое вхождение объекта, на который указывает ссылка. Если требуется получить несколько ключей, используйте функцию с табличным значением OPENJSON, как показано в следующем примере.
OPENJSON необходим уровень совместимости 130
Вопрос. Я пытаюсь выполнить OPENJSON в SQL Server 2016, но получаю следующую ошибку.
Msg 208, Level 16, State 1 'Invalid object name OPENJSON'
Ответ. Функция OPENJSON доступна только при уровне совместимости 130. Если уровень совместимости базы данных ниже 130, функция OPENJSON будет скрыта. Другие функции JSON доступны на всех уровнях совместимости.
Другие вопросы
Ключи ссылки, содержащие символы, отличные от буквенно-цифровых, в тексте JSON
Вопрос. Ключи в тексте JSON содержат символы, отличные от буквенно-цифровых. Как можно сослаться на эти свойства?
Ответ. Необходимо заключить их в кавычки в путях JSON. Например, JSON_VALUE(@json, '$."$info"."First Name".value') .
Дополнительные сведения о JSON в SQL Server и базе данных SQL Azure
Видео Майкрософт
Наглядные инструкции по встроенной поддержке JSON в SQL Server и базе данных SQL Azure см. в следующих видео.
SQL Server 2016 and JSON Support (SQL Server 2016 и поддержка JSON)
Using JSON in SQL Server 2016 and Azure SQL Database (Использование JSON в SQL Server 2016 и базе данных SQL Azure)
JSON as a bridge between NoSQL and relational worlds (JSON как мост между NoSQL и реляционными решениями)
Сериализуя этот объект в JSON, может быть получен следующий документ:
2. Объектная техника работы
2.1. Общая информация
Система «1С:Предприятие» поддерживает сериализацию следующих данных в формат JSON:
● Строка – сериализуется в строку;
● Число – сериализуется в число;
● Булево – сериализуется в литералы true и false;
● Неопределено – сериализуется в null
● Массив, ФиксированныйМассив – сериализуется в массив JSON в том случае, если любой элемент массива может быть сериализован в JSON.
● Структура, ФиксированнаяСтруктура – сериализуется в объект JSON:
● Ключ – ключ элемента структуры.
● Значение – значение элемента структуры в том случае, если значение может быть сериализовано в JSON.
● Соответствие, ФиксированноеСоответствие – сериализуется в объект JSON:
● Ключ – ключ элемента соответствия. Ключ может быть только значением типа Строка, в противном случае будет генерироваться исключение.
● Значение – значение элемента соответствия в том случае, если значение может быть сериализовано в JSON.
● Дата – формат сериализации определяется настройками.
● Если выполняется попытка сериализации типа, отсутствующего в данном списке – будет вызвано исключение.
При работе с объектной техникой, имеется возможность читать (и писать) данные в соответствие или структуру. Основное отличие между этими объектами состоит в том, что ключ элемента структуры подчиняется правилам формирования переменной на встроенном языке, а ключ элемента соответствия может быть любым. С учетом того, чтоб JSON не накладывает ограничений на значение ключа, не все JSON-документы можно
прочитать в структуру. Еще одним различием между структурой и соответствием является то, что к элементам структуры можно обращаться «через точку», а к элементам соответствия такой доступ не предоставляется. В связи с этим, может оказаться удобным получать данные в виде структуры, если ключи из JSON-документа соответствуют требованиям к ключам структур системы «1С:Предприятие».
Объектная техника предполагает достаточно простую работу с данными, однако платой за это является большой расход памяти, т. к. весь JSON-документ обрабатывается целиком в оперативной памяти.
2.2. Запись
Для того чтобы выполнить запись объекта в формате JSON, необходимо использовать (в простейшем случае) следующие объекты:
1. Собственно записываемый объект, например типа Структура.
2. Объект, обеспечивающий низкоуровневую запись данных в формате JSON – ЗаписьJSON.
3. Объект настроек сериализации НастройкиСериализацииJSON.
Метод глобального контекста ЗаписатьJSON() оперирует вышеперечисленными объектами. Рассмотрим пример, в котором потребуется записать структуру, которая состоит из трех элементов разного типа (но типы являются примитивными):
В результате работы данный пример сформирует следующий JSON-документ:
В результате работы данный пример сформирует следующий JSON-документ:
Если несколько расширить набор записываемых данных, например, добавить к ним значение типа УникальныйИдентификатор, то запись не будет выполнена. В результате исполнения кода:
Будет вызвано исключение:
Причиной такого поведения является то, что тип УникальныйИдентификатор не входит в состав JSON-сериализуемых типов данных системы «1С:Предприятие». Однако система предоставляет возможность «обойти» это ограничение: необходимо передать в функцию ЗаписатьJSON() имя функции обратного вызова, которая будет заниматься JSON-сериализацией неподдерживаемых объектов. Эта функция будет называться
функцией преобразования. При этом формат такой сериализации будет разрабатывать непосредственно сам прикладной разработчик. Надо понимать, что такая сериализация не будет универсальной, т. к. принимающая сторона, не обладающая знаниями о формате сериализации, не сможет прочитать переданные данные. Другими словами, формат сериализации необходимо разрабатывать совместно всеми сторонами обмена
такого рода данными.
С учетом вышесказанного, более сложный вариант обмена теперь происходит следующим образом:
● Вызывается функция сериализации объекта в формат JSON (ЗаписатьJSON()).
● Система «1С:Предприятие» для каждого элемента структуры, тип значения которого не сериализуется в формат JSON, будет вызываться функция преобразования.
● Функция преобразования анализирует переданный объект и принимает решение – отказаться от его записи или вернуть платформе значение, которое может быть сериализовано в JSON.
Доработанный код записи будет выглядеть следующим образом:
Следует обратить внимание, что функция преобразования должна быть объявлена с указанием ключевого слова Экспорт. Также следует помнить, что функция преобразования (в модуле управляемой формы) может быть описана только в «контекстной» части модуля, т. е. с использованием директивы компиляции &НаКлиенте или &НаСервере.
В результате работы приведенного примера будет сформирован следующий JSON-документ:
При создании функции преобразования следует помнить о следующих особенностях:
● Функция преобразования вызывается для значений всех типов, которые не поддерживают сериализацию в JSON (см. раздел 16.2.1).
● Если функция преобразования вернет значение, которое не может быть сериализовано в JSON – будет вызвано исключение.
● Если переданное значение является структурой, то вызов функции преобразования для элементов этой структуры будет вызваться до того, как в поток будет записано имя свойства этого элемента. В результате функция преобразования может отказаться от записи значения и структура формируемого JSON-документа не будет нарушена.
● Имя свойства будет передано в функцию преобразования только для элементов структур и соответствий.
2.3. Чтение
2.3.1. Общая схема
Чтение данных в объектной технике выглядит аналогично записи. Рассмотрим пример чтения файлов, которые формировались во время рассмотрения объектной записи (предыдущий раздел).
Документ имеет следующее содержание (с точностью до значения даты):
При чтении JSON-документа в переменную Данные будет сформирована структура вида:
Ключ = ДлинаЗаписи, значение = 20
Ключ = КлючЗаписи, значение = abcdefgh
Ключ = ДатаИзменения, значение = <значение даты и времени>
Такой вариант чтения хорошо подходит в том случае, если читаемые данные могут быть преобразованы в структуру или соответствие и все читаемые данные могут быть однозначно десериализованы без потери информации о типе. Если читаемые данные обладают сложной структурой или требуют выполнения дополнительных преобразований при чтении, то можно пойти двумя путями:
1. Получить соответствие (или структуру), в которое будет полностью загружен JSON-документ, и потом завершить преобразование с помощью обхода получившегося объекта.
2. Заниматься необходимым преобразованием непосредственно во время загрузки данных.
Для этого необходимо передать в функцию ПрочитатьJSON() имя функции обратного вызова, которая будет заниматься десериализацией JSON-данных в нужные объекты системы «1С:Предприятие». Эта функция будет называться функцией восстановления.
В обоих случаях прикладной разработчик должен знать, какие данные и в каком виде находятся JSON-документе. Далее будут подробно рассмотрены оба варианта загрузки данных. В качестве макетной задачи будет рассматриваться получение погоды в г. Москва с помощью некоторого интернет-сервиса. В качестве ответа интернет-сервис возвращает JSON-документ следующего содержания:
Кратко рассмотрим описание формата:
● id – идентификатор города;
● name – имя города;
● dt – дата и время получения погоды, в формате Unix, GMT;
● coord – местоположение города:
● lon – долгота;
● lan – широта.
● sys – дополнительная информация:
● country – страна расположения города;
● sunrise – время восхода Солнца в формате Unix, GMT;
● sunset – время заката Солнца, в формате Unix, GMT.
● weather – дополнительная информация о погоде:
● main – общая характеристика погоды;
● description – описание погоды.
● main – собственно описание погоды:
● temp – температура, в градусах Кельвина. Для получения градусов Цельсия необходимо вычесть 273.15;
● pressure – давление в гектопаскалях. Для перевода в миллиметры ртутного столба, надо значение давления умножить на 0,75.
● humidity – влажность в %.
● wind – параметры ветра:
● speed – скорость в милях в час. Для перевода в километры в час необходимо умножить на 1,61.
● deg – направление ветра, в градусах.
● clouds – информация об осадках:
● all – вероятность возникновения осадков, в %.
В результате загрузки этих данных должна получиться структура, где все времена представлены стандартным типом Дата, температура – в градусах Цельсия, скорость – в километрах в час, а давление – в миллиметрах ртутного столба.
Рассмотрим загрузку данной информации обоими способами. Данные записаны в файле c:\temp\weather.json.
2.3.2. Чтение с постобработкой
Собственно процесс чтения выглядит просто:
В результате в переменной Данные будет следующая информация:
Рис. 3 Результат загрузки
Без учета необходимости конвертации все выглядит предсказуемо. Однако дата и время автоматически не преобразовались. Можно попробовать указать системе на то, что поле dt (например) является полем, где находится дата и время:
Ошибка произошла потому, что система не понимает формат даты и времени, выраженной простым числом. Программный интерфейс работы с JSON предлагает функцию, помогающую выполнить конвертацию полей типа Дата – ПрочитатьДатуJSON(). Для использования этой функции необходимо привести десериализованную строку к формату, принятому, например, в JavaScript. В рассматриваемом примере получится
следующий программный текст:
В результате значение свойства Данные.dt станет равно значению 23.09.2014 13:35:40 (типа Дата). Остальная конвертация выполняется аналогичным образом.
2.3.3. Чтение с функцией восстановления
Вариант постобработкой выглядит не очень хорошо, если чтение JSON-документа предполагается выполнять в разных местах прикладного решения. В этом случае может возникнуть ситуация, когда код преобразования будет расположен в нескольких местах прикладного решения.
Хорошей заменой постобработки, в этом случае, является использование функции восстановления. Для применения функции восстановления необходимо описать саму функцию и несколько изменить само чтение документа:
В вышеуказанном примере присутствует особенность – функция восстановления будет вызвана для всех свойств, которые будут обнаружены в JSON-документе. Это не всегда удобно и, кроме того, существенно снижает производительность чтения JSON-документа (за счет вызова функции восстановления). Например, при чтении метеорологических данных нам необходимо выполнять особое преобразование только для свойств, в
которых содержится дата и время, а остальные свойства мы конвертировать не собираемся. Чтобы не анализировать в функции восстановления имя реквизита (как в вышеприведенном примере), можно поступить другим способом: явным образом передать в функцию чтения JSON-документа список реквизитов, которые содержат дату и время, а функцию восстановления написать исходя из того, что эта функция будет вызвана только для необходимых свойств. В результате получится следующий код:
Следует обратить внимание, что функция восстановления должна быть объявлена с указанием ключевого слова Экспорт. Также следует помнить, что функция восстановления (в модуле управляемой формы) может быть описана только в «контекстной» части модуля, т. е. с использованием директивы компиляции &НаКлиенте или &НаСервере. При разработке функции восстановления необходимо принимать во внимание тот факт, что свойства документа считываются не в том порядке, как они представлены в файле.
Рассмотрим последовательность, в которой свойства JSON-документа попадают в функцию восстановления. Для этого разместим в таблице каждое свойство файла и то, в каком порядке будет прочитано свойство:
В общем случае, можно сформулировать следующее правило обхода: первым будет прочитано свойство, которому не подчинено ни одно другое свойство. Например, свойству id не подчинено никакое свойство, и оно считывается первым. Однако свойству coord подчинено свойства lon и lat, поэтому вначале будут считаны эти свойства, а лишь затем – свойство coord, которое в качестве значения получит структуру (или соответствие) из подчиненных свойств документа.
3. Работа с XDTO-объектами
3.1. Общая информация
Работа с XDTO-объектами, в основном, ориентирована на обмен информации между системами, написанными на платформе «1С:Предприятие».
Однако сам механизм не накладывает никаких ограничений на его использование для обмена с другими системами.
JSON-сериализация XDTO-объекта выполняется сразу в JSON-документ, без формирования в памяти полной структуры сериализуемых объектов.
Также следует учитывать, что JSON-сериализация «эмулирует» XML-сериализацию, в силу чего получающийся JSON-документ внешне выглядит очень похоже на соответствующий XML-документ.
В JSON-документ могут быть помещены любые объекты системы «1С:Предприятие», для которых указано, что они могут быть сериализованы в XDTO. При попытке выполнить сериализацию значения неподдерживаемого типа будет вызвано исключение.
3.2. Запись
Для того чтобы выполнить запись XDTO-объекта в формате JSON, необходимо использовать (в простейшем случае) следующие объекты:
1. Собственно записываемый объект, поддерживающий преобразование в/из XDTO, например, элемент справочника.
2. Сериализатор XDTO-объектов – СериализаторXDTO;
3. Объект, обеспечивающий низкоуровневую запись данных в формате JSON – ЗаписьJSON.
4. Объект настроек сериализации НастройкиСериализацииJSON.
Собственно сериализация выполняется с помощью метода ЗаписатьJSON() объекта СериализаторXDTO. Рассмотрим пример сериализации данных типа СправочникОбъект. В качестве примера используется справочник Валюты, который содержит поля Курс (типа Число) и ДатаКурса (типа Дата):
Сериализация значений типа Дата выполняется в формате ISO (определяется механизмом XDTO) и не управляется при записи данных. Также не поддерживается использование функции преобразования при операции сериализации, в отличие от потоковой (см. раздел 16.2.4) и объектной (см. раздел 16.2.2) техник.
Также следует помнить о следующей особенности: при записи объекта не формируется его тип, поэтому после JSON-сериализации XDTO-объекта отсутствует возможность выполнить десериализацию без указания типа считываемого объекта. Предыдущий пример сериализации элемента справочника Валюты будет невозможно десериализовать без явного указания типа значения. Чтобы упростить ситуацию, можно воспользоваться
параметром НазначениеТипаXML метода ЗаписатьJSON() объекта СериализаторXDTO. Если в качестве значения этого параметра указать НазначениеТипаXML.Явное, то появится возможность выполнить десериализацию без явного указания типа, а сформированный файл будет выглядеть следующим образом:
С помощью JSON возможно выполнить сериализацию XDTO-объектов, которые не соответствуют какой-либо схеме. В этом случае используется явное описание типов реквизитов, одноименные свойства не будут объединяться в массив, а будут выводиться в JSON-документ поэлементно, в соответствии с XDTO-объектом.
Пример:
3.3. Чтение
В общем случае, чтение XDTO-объекта из JSON-документа аналогично записи. Чтение выполняется с помощью механизма чтения XDTO-объектов из XML-файла, поэтому чтение выполняется со следующими ограничениями:
● Возможно чтение только тех объектов, для которых существует XDTO-сериализация.
● Свойства в JSON-документе должны следовать в том же порядке, как и в XDTO-объекте.
● В случае если читаемый объект не соответствует схеме – будет вызвано исключение.
● Имеется возможность выполнять чтение произвольного JSON-документа в объект XDTO (ОбъектXDTO) с помощью фабрики XDTO (ФабрикаXDTO). Такое чтение возможно в том случае, если:
● фабрика XDTO, с помощью которой выполняется чтение, «знает» о типах, которые присутствуют в JSON-документе, из которого производится чтение.
● все элементы JSON указаны без явного указания типов и элементов, специфичных для JSON-документов, формируемых при сериализации объектов XDTO.
Выполнить чтение JSON-документа в том случае, если в нем используются типы, которые неизвестны фабрике XDTO, с помощью которой выполняется чтение документа – невозможно.
Рассмотрим пример чтения некоторого JSON-документа, например, полученного при работе примера работы со справочником Валюты из предыдущего раздела .
В результате работы примера в переменно Данные будет помещен объект типа СправочникОбъект.Валюты для валюты с кодом 978. Однако данное поведение будет наблюдаться только в том случае, если при выполнении JSON-сериализация значение параметра НазначениеТипаXML было установлено в значение Явное. В противном случае при попытке чтения (как указано выше) будет вызвано исключение. При чтении объекта с
неявным указанием типа объекта, читаемый тип можно передать в виде параметра метода ПрочитатьJSON(). В этом случае пример будет выглядеть следующим образом:
4. Потоковая техника работы
4.1. Общая информация
Потоковая техника работы с документом ориентирована на то, что документ целиком не загружается в память и обрабатывается последовательно, от элемента к элементу. Например, если надо прочитать только какой-то объект из JSON-документа, то потоковая техника может дать существенный выигрыш, особенно в том случае, если требуемый элемент находится в начале обрабатываемого документа.
4.2. Запись
Для того чтобы выполнить потоковую запись JSON-документа, необходимы записываемые данные и объект ЗаписьJSON. При этом следует понимать, что формирование корректной структуры JSON-документа полностью лежит на прикладном разработчике, который формирует документ. Для упрощения такого контроля объект ЗаписьJSON имеет свойство ПроверятьСтруктуру.
Рассмотрим простой пример записи документа:
В результате исполнения этого программного кода будет сформирован следующий документ:
Такой формат документа удобен для визуального просмотра, но занимает больше места. Можно изменить значение первого параметра конструктора ПараметрыЗаписиJSON на значение ПереносСтрокJSON.Нет и результирующий документ примет такой вид (разница составит примерно 20%):
4.3. Чтение
Потоковое чтение JSON-документа выполняется аналогично его записи: прикладной разработчик в цикле читает следующий элемент, определяет, что считано и обрабатывает считываемые данные.
Примитивный случай потокового чтения документа может выглядеть следующим образом:
При исполнении данного кода предполагается, что:
● Переменная КогдаСформировано содержит значение типа Дата. Содержит дату и время формирования JSON-документа.
● Переменная СписокЗаказов является массивом ссылок на документы заказов.
Исполнение данного код приведет к формированию следующего JSON-документа:
Изменяя значения параметров объектов НастройкиСериализации и ПараметрыJSON, а также манипулируя параметрами метода ЗаписатьДатуJSON(), можно изменять результирующий JSON-документ для максимального соответствия «ожиданиям» принимающей системы.
JSON (JavaScript Object Notation) - это текстовый формат для хранения и обмена данными.
JSON по синтаксису очень похож на Python и достаточно удобен для восприятия.
Как и в случае с CSV, в Python есть модуль, который позволяет легко записывать и читать данные в формате JSON.
Чтение¶
Для чтения в модуле json есть два метода:
- json.load - метод считывает файл в формате JSON и возвращает объекты Python
- json.loads - метод считывает строку в формате JSON и возвращает объекты Python
json.load ¶
Чтение файла в формате JSON в объект Python (файл json_read_load.py):
Вывод будет таким:
json.loads ¶
Считывание строки в формате JSON в объект Python (файл json_read_loads.py):
Результат будет аналогичен предыдущему выводу.
Запись¶
Запись файла в формате JSON также осуществляется достаточно легко.
Для записи информации в формате JSON в модуле json также два метода:
- json.dump - метод записывает объект Python в файл в формате JSON
- json.dumps - метод возвращает строку в формате JSON
json.dumps ¶
Преобразование объекта в строку в формате JSON (json_write_dumps.py):
Метод json.dumps подходит для ситуаций, когда надо вернуть строку в формате JSON. Например, чтобы передать ее API.
json.dump ¶
Запись объекта Python в файл в формате JSON (файл json_write_dump.py):
Когда нужно записать информацию в формате JSON в файл, лучше использовать метод dump.
Дополнительные параметры методов записи¶
Методам dump и dumps можно передавать дополнительные параметры для управления форматом вывода.
По умолчанию эти методы записывают информацию в компактном представлении. Как правило, когда данные используются другими программами, визуальное представление данных не важно. Если же данные в файле нужно будет считать человеку, такой формат не очень удобно воспринимать.
К счастью, модуль json позволяет управлять подобными вещами.
Передав дополнительные параметры методу dump (или методу dumps), можно получить более удобный для чтения вывод (файл json_write_indent.py):
Теперь содержимое файла sw_templates.json выглядит так:
Изменение типа данных¶
Еще один важный аспект преобразования данных в формат JSON: данные не всегда будут того же типа, что исходные данные в Python.
Например, кортежи при записи в JSON превращаются в списки:
Так происходит из-за того, что в JSON используются другие типы данных и не для всех типов данных Python есть соответствия.
Таблица конвертации данных Python в JSON:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float | number |
True | true |
False | false |
None | null |
Таблица конвертации JSON в данные Python:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
Ограничение по типам данных¶
В формат JSON нельзя записать словарь, у которого ключи - кортежи:
С помощью дополнительного параметра можно игнорировать подобные ключи:
Кроме того, в JSON ключами словаря могут быть только строки. Но, если в словаре Python использовались числа, ошибки не будет. Вместо этого выполнится конвертация чисел в строки:
Читайте также: