Windows data json jsonobject

Разбор JSON-строк в компонентах Windows Runtime

Посетителей: 794 | Просмотров: 909 (сегодня 0) Шрифт:

Приложения Windows Store на JavaScript может создавать любой, кто умеет разрабатывать неуправляемые Windows-приложения с применением HTML и JavaScript, но JavaScript не всегда является лучшим выбором. Какое-то поведение в ваших приложениях может быть эффективнее реализовано на более объектно-ориентированных языках вроде C#, Visual Basic или C++. Кроме того, определенные части кода могут оказаться подходящими кандидатами для повторного использования в нескольких компонентах Windows Runtime (WinRT), которым нужны данные от UI-уровня. Передача данных из JavaScript в WinRT-компоненты и обратно в UI важна для понимания в любой из этих ситуаций.

В Web данные часто передаются от клиента серверу и обратно в виде JSON-объектов. В различных контекстах инфраструктуры, подобные ASP.NET Web Forms и ASP.NET MVC, предоставляют такие средства, как механизмы связывания моделей (model binders) или, как минимум, какую-то форму «волшебной» обработки на серверной стороне для разбора JSON-объектов. WinRT-компоненты имеют объекты с поддержкой разбора JSON, но эта поддержка низкоуровневая, и во многих случаях требует явной обработки с вашей стороны.

В этой статье демонстрируется, как надежно разбирать JSON-строки, передаваемые в WinRT-компоненты, чтобы получать строго типизированные объекты и возвращать результат обратно в UI.

Ограничения во взаимодействии с WinRT-компонентами

Прежде чем обсуждать конкретику разбора JSON-объектов, нужно сначала ознакомиться с требованиями и ограничениями во взаимодействии с WinRT-компонентами. В справочном разделе MSDN «Creating Windows Runtime Components in C# and Visual Basic» (bit.ly/WgBBai) детально описано, что необходимо для WinRT-компонентов при объявлении параметров методов и возвращаемых типов. Допустимые типы по большей части состоят из элементарных типов и ряда типов наборов, поэтому попытка передать исходный JSON-объект в компонент будет отклонена. Лучший способ передачи JSON-объекта в управляемый компонент — сначала сериализовать его (используя метод JSON.stringify), так как строки полностью поддерживаются этими классами.

Разбор JSON-объектов в управляемом коде

Пространство имен Windows.Data.Json включает ряд классов, предназначенных для работы с JSON-объектами в строго типизированном стиле, в том числе классы JsonValue, JsonArray и JsonObject. Класс JsonValue представляет значение JSON, выраженное в виде строки, числа, булева значения, массива или объекта (детали см. по ссылке bit.ly/14AcTmF). Разбор JSON-строки требует передачи исходной строки в JsonValue, который затем вернет экземпляр JsonObject.

Класс JsonObject представляет полный JSON-объект и включает методы для манипуляций над исходным объектом. Через класс JsonObject можно добавлять и удалять члены, извлекать данные из членов, перебирать все члены и даже вновь сериализовать этот объект. Подробнее о JsonObject см. по ссылке bit.ly/WDWZkG.

Класс JsonArray представляет JSON-массив, который опять же включает целый набор методов для управления массивом, в частности для итерации, добавления и удаления элементов массива. Подробнее об интерфейсе класса JsonArray см. по ссылке bit.ly/XVUZo1.

В качестве примера рассмотрим, как приступить к использованию этих классов, и для этого возьмем следующий JSON-объект в JavaScript:

Прежде чем передавать этот объект WinRT-компоненту, вы должны сериализовать его в строку, используя функцию JSON.stringify. Заметьте, что происходит после сериализации объекта: тот же объект представляется следующим образом:

Читайте также:  Как настроить сеть windows smb

Это может оказаться сюрпризом для вас, так как вызов той же функции в веб-браузере просто сериализует объект в строку без добавления каких-либо членов в объект. Это изменение в структуре JSON-строки влияет на то, как вы извлекаете данные из объекта.

Первый шаг в считывании этих данных в WinRT-компоненте — попытка разобрать входную строку как экземпляр JsonValue. Если это удается, тогда вы можете запросить JsonObject от корневого экземпляра JsonValue. В этом случае JsonValue является корневым объектом, созданным вызовом функции stringify, и JsonObject предоставляет вам доступ к исходному объекту, с которого вы начинали в JavaScript-коде.

Следующий код показывает, как использовать метод GetNamedString (после того, как JsonObject становится доступен) для извлечения значения члена «firstName» в переменную:

Аналогичный подход применяется для доступа к булевым и числовым членам, где доступны методы GetNamedBoolean и GetNamedNumber. Следующий шаг состоит в реализации методов расширения JsonObject, чтобы упростить доступ к JSON-данным.

Методы расширения для JsonObject

Исходная реализация класса JsonObject предоставляет низкоуровневое поведение, которое можно значительно расширить некоторыми простыми методами, позволяющими обрабатывать неидеальное форматирование и избегать исключений, если какие-то члены отсутствуют в источнике. Иначе говоря, объекты, созданные в JavaScript, неизбежно вызывают проблемы с форматированием или структурой, которые могли бы привести к исключениям. Добавление следующих методов расширения в класс JsonObject поможет снять остроту этих проблем.

Первый добавляемый метод расширения — GetStringValue. Его реализация показана на рис. 1, и он сначала проверяет, что член существует в объекте. В данном случае параметр key — это имя свойства JSON-объекта. Если данный член существует, вызывается метод TryGetValue, чтобы попытаться получить данные из экземпляра JsonObject. Если значение найдено, оно возвращается в виде объекта, реализующего интерфейс IJsonValue.

Рис. 1. Реализация метода расширения GetStringValue

Интерфейс IJsonValue включает свойство ValueType только для чтения, которое предоставляет значение из перечисления JsonValueType, обозначающее тип данных объекта. После согласования ValueType для получения данных из объекта используется соответствующим образом типизированный метод.

Метод GetStringValue распознает булевы и числовые значения, обеспечивая защиту от неправильно структурированных JSON-объектов. Вы могли бы сделать свою реализацию более строгой и отказываться от передачи или генерировать ошибку, если JSON-объект имеет не совсем правильный формат для ожидаемого типа, но код в моем примере более гибок при разборе и защищает от ошибок.

Следующий метод расширения (рис. 2) — реализация для извлечения булевых значений. В данном случае метод GetBooleanValue поддерживает булевы значения, выражаемые строками (например, значение true выражается как «1» или «true» и т. д.) и числами (скажем, true = 1, а false = 0).

Рис. 2. Реализация метода расширения GetBooleanValue

Методы расширения для числовых типов настроены на возврат типов, которые могут содержать null-значения (nullable types), поэтому в данном случае GetDoubleValue возвращает double, допускающий null-значение. Корректирующая логика в этом случае пытается преобразовать строки в возможные числовые значения (рис. 3).

Рис. 3. Реализация метода расширения GetDoubleValue

Поскольку встроенный метод для извлечения чисел в классе JsonObject возвращает double, а значения данных зачастую выражаются как целые, следующий код показывает, как метод GetIntegerValue обертывает метод GetDoubleValue и преобразует результат в целочисленное значение:

Читайте также:  Linux как узнать версию установленного пакета

Добавление поддержки фабрики

Теперь, когда класс JsonObject расширен и включает некоторую высокоуровневую поддержку извлечения данных в элементарные типы, нашим следующим шагом будет использование этой поддержки в классах фабрики, отвечающих за принятие входных JSON-строк и возврат экземпляра объекта предметной области (domain object).

Следующий код иллюстрирует, как в этой системе моделируется некая персона:

Ниже показан метод Create в классе PersonFactory, который принимает строку:

На рис. 4 представлен метод Create, принимающий JsonValue. Эти методы Create, используемые совместно, отвечают за прием исходной строки и возврат экземпляра класса Person с ожидаемыми данными в каждом его члене. Методы разделены и перегружены, чтобы обеспечить поддержку JSON-массивов (поясняется в следующем разделе).

Рис. 4. Метод Create класса PersonFactory, принимающий JsonValue

Добавление поддержки массивов

Иногда ваши данные поступают в виде массивов объектов, а не отдельных объектов. В этом случае вы должны попытаться разобрать строку как массив, используя класс JsonArray. На рис. 5 показано, как входная строка разбирается в массив и каждый элемент передается методу Create для окончательного разбора в модель. Заметьте, что сначала создается новый экземпляр списка Person на тот случай, если строку не удастся разобрать в массив объектов; тогда результатом будет пустой массив, что поможет избежать неожиданных исключений.

Рис. 5. Метод CreateList класса PersonFactory

Добавление поддержки классов

Теперь нужно создать объект, отвечающий за использование класса фабрики и делающий что-то интересное с получаемыми экземплярами модели. Рис. 6 демонстрирует, как используются индивидуальные строки и строки JSON-массива, которые потом обрабатываются как строго типизированные объекты.

Рис. 6. Реализация ContactsManager (без поддержки асинхронности)

Поддержка асинхронного взаимодействия

Вызовы методов WinRT-компонентов должны осуществляться асинхронно, так как JSON-сообщения потенциально способны достигать произвольного размера, что может вызвать задержки в вашем приложении.

Следующий код включает метод, добавленный в ContactsManager для поддержки асинхронного доступа к методу AddContact:

Метод AddContactAsync принимает JSON-строку, а затем запускает Task, который делает все, что нужно для выполнения метода AddContact. По завершении Task ответ посылается в JavaScript-обещание (promise), что облегчается благодаря поддержке интерфейса IAsyncOperation. Полный исходный код класса ContactsManager с асинхронной поддержкой как AddContact, так и AddContacts вы найдете в пакете кода, который можно скачать для этой статьи.

Выполнение обещаний в JavaScript

Последняя часть головоломки — использование класса ContactsManager в JavaScript и вызовы этого класса по шаблону обещаний (promise pattern). Подход, применяемый в этом примере, заключается в реализации модели представления, которая передает смоделированные данные WinRT-компоненту, а затем ждет ответ. Данные, передаваемые компоненту, определены на рис. 7; они включают один JSON-объект, а также массив.

Рис. 7. Источник данных JSON

Модель представления, показанная на рис. 8, содержит член для модели и члены для сообщений, возвращаемых WinRT-компонентом. Инфраструктура связывания Windows Library for JavaScript (WinJS) обеспечивает привязку сообщений, возвращаемых из ответа, к HTML-элементам. Полный листинг модуля страницы доступен в сопутствующем этой статье пакете кода, и вы можете посмотреть в нем, как сведены воедино все части.

Рис. 8. Модель представления, использующая ContactsManager

Json Object Class

Definition

Represents a JSON object containing a collection of name and JsonValue pairs.

JsonObject is an activatable class that implements JsonValue and the IMap interface such that its name/value pairs can be manipulated like a dictionary. When there are values with duplicated names, the last name/value pair will be stored.

Читайте также:  Бовет чезати ядро линукс

Windows 10 requirements

Remarks

For an example of how these class methods are used to parse an object from a JSON string and convert it into a JsonObject object, update the name/value pairs the object contains, and then serialize the updated JsonObject object as a JSON string, see Using JavaScript Object Notation (JSON).

Constructors

Initializes a new instance of a JsonObject that represents a JSON object containing a collection of name and JsonValue pairs.

Properties

Gets the size (count) of the collection.

Gets the type of the encapsulated JSON value. Possible types are defined by JsonValueType.

Methods

Removes all items from the collection.

Returns the iterator for iteration over the key/value pairs in the JsonObject.

Returns a JsonArray if the ValueType of the encapsulated value is Array.

Gets a Boolean if the ValueType of the encapsulated value is Boolean.

Gets the JsonArray value with the specified name.

Gets the JsonArray value with the specified name, or the provided default value if no such named value is found.

Gets the Boolean value with the specified name.

Gets the Boolean value with the specified name, or the provided default value if no such named value is found.

Gets the number value (a Double) with the specified name.

Gets the number value (a Double) with the specified name, or the provided default value if no such named value is found.

Gets the JsonObject value with the specified name.

Gets the JsonObject value with the specified name, or the provided default value if no such named value is found.

Gets the String value with the specified name.

Gets the String value with the specified name, or the provided default value if no such named value is found.

Gets the JsonValue value with the specified name.

Gets the specified JsonValue value, or the provided default value if no such named value is found.

Gets the number (a Double) if the ValueType of the encapsulated value is Number.

Gets the JsonObject if the ValueType of the encapsulated value is Object.

Gets the String if the ValueType of the encapsulated value is String.

Indicates whether the JsonObject has an entry with the requested key.

Adds a new entry to the JsonObject.

Gets the JSON value associated with the supplied key, if an entry with that key exists.

Parses the specified JSON string that represents a JsonObject into a JSON value.

This will throw an exception if the provided JSON string is not valid. Use of JsonObject.TryParse is a recommended alternative. A TryParse call will return a boolean value to indicate success or failure and, if successful, the resultant JsonObject.

Removes a specific item from the JsonObject.

Sets the value of the first JsonValue object with the specified name to the specified value. If no such object is found, a new name and JsonValue pair is inserted into the JSON object.

Retrieves the JSON representation of the encapsulated value.

Retrieves the JSON representation of the encapsulated value.

Parses the specified string that represents a JSON object into a JsonObject.

Оцените статью