Работа с JSON
В «1С:Шине» представлены широкие возможности по работе с форматом JSON. Во встроенном языке используются специальные типы для работы с данным форматом, основными из которых являются СериализацияJson, ЧтениеJson и ЗаписьJson. Вы можете автоматически преобразовать в/из JSON большинство типов встроенного языка.
Эти и другие встроенные средства позволяют осуществлять потоковую, объектную или смешанную формы работы с форматом JSON:
- При потоковой работе документ JSON не загружается в память целиком, а считывается по частям. Программа при этом осуществляет навигацию по структуре документа в соответствии с настройками, указанными пользователем. Такой способ удобен при работе с файлами большого размера и/или сложной структурой вложенности объектов.
- При объектной работе документ JSON загружается в память целиком и считывается в объект, например, соответствие или структуру данных. Такой способ удобен, когда требуется передавать данные как простой и относительно небольшой объект, поэтому объекты JSON используются в основном в API.
В облаке установлено ограничение на объем чтения из потока и записи в поток — 1 Мбайт (подробнее). Для объектов, превышающих этот размер, следует использовать потоковый режим.
- При смешанной работе программа осуществляет навигацию по структуре документа потоковым способом, но, когда доходит до требуемого объекта, загружает его объектным способом.
Для тех, кто использует JSON версии JSON5 и выше (в которых поддерживаются однострочные комментарии)
Комментарий начинается с символов // и заканчивается с концом строки. Содержимое комментария при чтении JSON игнорируется, то есть результат чтения JSON не включает содержимого комментариев и не содержит какой-либо информации о наличии комментариев.
Потоковый режим работы с JSON
Во встроенном языке для потокового ввода и вывода данных используются соответственно типы ЧтениеJson и ЗаписьJson.
В типе ЧтениеJson существует метод для чтения значения JSON в указанный тип:
ПрочитатьСодержимое(), который использует обобщенный тип данных и принимает как аргумент объект типаНастройкиЧтенияОбъектовJson, как и в примере выше дляСериализацияJson.
Кроме того, существуют методы для чтения значения JSON в один из конкретных типов:
ПрочитатьСодержимоеКакБайты(),ПрочитатьСодержимоеКакБулево(),ПрочитатьСодержимоеКакВремя(),ПрочитатьСодержимоеКакДата(),ПрочитатьСодержимоеКакДатаВремя(),ПрочитатьСодержимоеКакДлительность(),ПрочитатьСодержимоеКакМассив(),ПрочитатьСодержимоеКакМомент(),ПрочитатьСодержимоеКакСоответствие(),ПрочитатьСодержимоеКакСтроку(),ПрочитатьСодержимоеКакУуид(),ПрочитатьСодержимоеКакЧисло().
Объектный режим работы с JSON
Во встроенном языке для объектной работы с данными используются механизмы сериализации и десериализации. Сериализация используется для перевода структуры данных в формат, позволяющий передавать или хранить эти данные, например, в файле. Десериализация — обратная процедура. В «1С:Шине» для этого используется тип СериализацияJson. Методы этого типа позволяют выполнить сериализацию (метод ЗаписатьОбъект() и др.) в поток или строку или десериализацию (метод ПрочитатьОбъект() и др.).
При сериализации порядок разбора значений следующий:
-
Для 4-х простых базовых типов зап исывается только значение:
При десериализации порядок разбора значений следующий:
-
Нетипизированное чтение:
Сначала предпринимается попытка разобрать значения 4-х простых базовых типов:
И 2-х сложных:
Если разобрать значение не удалось, то будет выброшено исключение чтения JSON.
-
Типизированное чтение:
Сначала предпринимается попытка разобрать значения 4-х простых базовых типов, если указаны они или их базовые типы:
Если разобрать значение не удалось, то будет осуществляться обход всех доступных типов значения. Если в результате обхода значение разобрать удалось, но сразу несколькими типами, то будет выброшено исключение о неявном чтении.
Смешанный режим работы с JSON
При смешанной работе с JSON могут использоваться как типы ЧтениеJson и ЗаписьJson, так и тип СериализацияJson. Например:
// Создаем структуру для чтения данных из JSON
структура ФизическоеЛицо
пер Фамилия: Строка
пер Имя: Строка
пер Отчество: Строка
;
// Используем потоковое чтение с помощью типа ЧтениеJson
@НаСервере @ДоступноСКлиен та
метод ПрочитатьФизическихЛиц()
пер ФизическиеЛицаJson =
"[
{
\"Фамилия\": \"Иванов\",
\"Имя\": \"Иван\",
\"Отчество\": \"Иванович\"
},
{
\"Фамилия\": \"Петров\",
\"Имя\": \"Петр\",
\"Отчество\": \"Петрович\"
}
]"
пер Чтение = новый ЧтениеJson(ФизическиеЛицаJson)
// Позиционируемся на начало массива
если не Чтение.Следующий()
возврат
;
// Позиционируемся на первый элемент массива
если не Чтение.Следующий()
возврат
;
// Считываем данные из JSON в структуру для дальнейшего использования как объекта
пока Чтение.ВидУзла != ВидУзлаJson.КонецМассива
пер ФизЛицо = Чтение.ПрочитатьСодержимое<ФизическоеЛицо>()
// Записываем полученные данные в базу
;
;
Или другой пример:
// Используем потоковое чтение с помощью типа ЧтениеJson
@НаСервере @ДоступноСКлиента
метод ПрочитатьОбращенияПользователей()
пер ОбращенияJson =
"[
{\"Пользователь\":
{
\"Фамилия\": \"Иванов\",
\"Имя\": \"Иван\",
\"Логин\": \"Иванов\"
},
\"Обращения\": [
{\"Категория\": \"Жалоба\", \"Текст\": \"текст1\"},
{\"Категория\": \"Вопрос\", \"Текст\": \"текст2\"}
]
},
{\"Пользователь\":
{
\"Фамилия\": \"Петров\",
\"Имя\": \"Петр\",
\"Логин\": \"Петров\"
},
\"Обращения\": [
{\"Категория\": \"Благодарность\", \"Текст\": \"текст3\"}
]
}
]"
пер Чтение = новый ЧтениеJson(ОбращенияJson)
// Позиционируемся на начало массива
если не Чтение.Следующий()
возврат
;
// Позиционируемся на первый элемент массива
если не Чтение.Следующий()
возврат
;
пока Чтение.ВидУзла != ВидУзлаJson.КонецМассива
// Позиционируемся на свойство Пользователь
Чтение.Следующий()
// Позиционируемся на начало объекта Пользователь
Чтение.Следующий()
// Считываем данные из JSON в коллекции для дальнейшего использования как объектов
// Читаем данные пользователя в соответствие
пер ДанныеПользователя = Чтение.ПрочитатьСодержимоеКакСоответствие()
// После этого вызова ЧтениеJson будет спозиционировано на свойство Обращения
// Позиционируемся на начало массива
Чтение.Следующий()
// Читаем массив обращений
пер Обращения = Чтение.ПрочитатьСодержимоеКакМассив()
// После этого вызова ЧтениеJson будет спозиционировано на токен КонецОбъекта
// Возвращаемся к потоковому чтению JSON
// Переходим к следующему элементу массива
Чтение.Следующий()
;
;
При смешанной работе с JSON в качестве параметров методов ПрочитатьОбъект() и ЗаписатьОбъект() типа СериализацияJson можно использовать экземпляры типов ЧтениеJson и ЗаписьJson. В таком случае при чт ении и записи этих объектов будут использоваться те же потоки, что и при их создании.
// Перечисление способов оплаты с указанием JSON-представления
перечисление ТипОплаты
Наличные,
@JsonЭлементПеречисления("КредитнаяКарта")
Карта умолчание
;
// Структура заказа
структура ИнформацияЗаказа
пер НомерЗаказа: Строка
пер ТипОплаты: ТипОплаты
пер Плательщик: Строка
;
// Метод формирования списка ИнформацияЗаказа
метод СоздатьСписокЗаказов(): Массив<ИнформацияЗаказа>
пер Результат = новый Массив<ИнформацияЗаказа>()
Результат.Добавить(новый ИнформацияЗаказа("abc-322", ТипОплаты.Карта, "Иванов"))
Результат.Добавить(новый ИнформацияЗаказа("abc-323", ТипОплаты.Наличные, "Петров"))
Результат.Добавить(новый ИнформацияЗаказа("abc-324", ТипОплаты.Карта, "Сидоров"))
возврат Результат
;
// Пример записи JSON с сериализацией
@НаСервере @ДоступноСКлиента
метод ЗаписатьСписокЗаказовВJson()
// Буфер для записи
пер Поток = новый СтроковыйПотокЗаписи()
// Настройки записи объектов в JSON (с валидацией)
знч Настройки = новый НастройкиЗаписиОбъектовJson()
// Реализация настроек ...
// Используем СтроковыйПотокЗаписи при создании экземпляра типа ЗаписьJson
пер Писатель = новый ЗаписьJson(Поток, Настройки)
Писатель.ЗаписатьНачалоОбъекта()
Писатель.Записать("Описание", "Список заказов")
Писатель.Записать("МеткаВремени", DateTime{2014-10-06T12:57:35})
Писатель.ЗаписатьИмяСвойства("Заказы")
// Используем экземпляр типа Запись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.ИнициализироватьОтсутствующиеПоляиНастройкиЧтенияОбъектовJson.ИнициализироватьПустыеКоллекции(параметрПропускатьПустыеЗначения);НастройкиЗаписиОбъектовJson.РежимЗаписиТипа(параметрРежимЗаписиТипа);НастройкиЧтенияОбъектовJson.ИгнорироватьНеизвестныеСвойства(параметрИгнорироватьНеизвестные).
-
@JsonСвойство(Имя, БезОбработки, Псевдонимы)
Данной аннотацией помечается поле структуры. Позволяет задать настройки для свойства, аналогичные следующим:
НастройкиЗаписиОбъектовJson.ИспользуемыеИменаСвойств(параметрИмя);НастройкиЗаписиОбъектовJson.СвойстваЗаписываемыеБезОбработки(параметрБезОбработки);НастройкиЧтенияОбъектовJson.ПсевдонимыСвойств(параметрПсевдонимы).
-
@JsonЭлементПеречисления(Имя, Псевдонимы)
Данной аннотацией помечается элемент перечисления. Позволяет задать настройки для свойства, аналогичные следующим:
НастройкиЗаписиОбъектовJson.ИспользуемыеИменаСвойств(параметрИмя);НастройкиЧтенияОбъектовJson.ПсевдонимыСвойств(параметрПсевдонимы).