Постановка задачи
Необходимо сериализовать словарь или массив в объект JSON, который можно передавать по сети или просто сохранять на диск.
Решение
Воспользуйтесь методом dataWithJSONObject: options: error: класса NSJSONSerialization.
Обсуждение
Метод dataWithJSONObject: options: error: класса NSJSONSerialization может сериализовывать словари и массивы, в которых содержатся лишь экземпляры переменных NSString, NSNumber, NSArray, NSDictionary либо NSNull для нулевых значений. Как было указано ранее, объект, передаваемый этому методу, должен быть либо массивом, либо словарем.
Теперь создадим простой массив с несколькими ключами и значениями:
NSDictionary *dictionary =
@{
@"First Name": @"Anthony",
@"Last Name": @"Robbins",
@"Age": @51,
@"children": @[
@"Anthony's Son 1",
@"Anthony's Daughter 1",
@"Anthony's Son 2",
@"Anthony's Son 3",
@"Anthony's Daughter 2"
],
};
Как видите, в этом словаре содержатся имя, фамилия и возраст Энтони Роббинса. Ключ словаря, называемый children, содержит имена детей Энтони. Это массив строк, где каждой строкой представлен один ребенок. Итак, на данный момент переменная dictionary содержит все значения, которые мы хотели в нее поместить. Теперь нужно сериализовать ее в объект JSON:
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization
dataWithJSONObject: dictionary
options: NSJSONWritingPrettyPrinted
error:&error];
if ([jsonData length] > 0 &&
error == nil){
NSLog(@"Successfully serialized the dictionary into data = %@", jsonData);
}
else if ([jsonData length] == 0 &&
error == nil){
NSLog(@"No data was returned after serialization.");
}
else if (error!= nil){
NSLog(@"An error happened = %@", error);
}
Возвращаемым значением метода dataWithJSONObject: options: error: являются данные типа NSData. Правда, эти данные можно просто преобразовать в строку и вывести на консоль. Для этого применяется метод-инициализатор initWithData: encoding: класса NSString. Далее приведен полный пример, в котором словарь преобразуется в объект JSON. Этот объект превращается в строку, а строка выводится в окне консоли:
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *dictionary =
@{
@"First Name": @"Anthony",
@"Last Name": @"Robbins",
@"Age": @51,
@"children": @[
@"Anthony's Son 1",
@"Anthony's Daughter 1",
@"Anthony's Son 2",
@"Anthony's Son 3",
@"Anthony's Daughter 2"
],
};
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization
dataWithJSONObject: dictionary
options: NSJSONWritingPrettyPrinted
error:&error];
if ([jsonData length] > 0 &&
error == nil){
NSLog(@"Successfully serialized the dictionary into data.");
NSString *jsonString = [[NSString alloc] initWithData: jsonData
encoding: NSUTF8StringEncoding];
NSLog(@"JSON String = %@", jsonString);
}
else if ([jsonData length] == 0 &&
error == nil){
NSLog(@"No data was returned after serialization.");
}
else if (error!= nil){
NSLog(@"An error happened = %@", error);
self.window = [[UIWindow alloc]
initWithFrame: [[UIScreen mainScreen] bounds]];
// Точка переопределения для дополнительной настройки после запуска приложения
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Запустив это приложение, вы увидите в окне консоли следующие результаты:
Successfully serialized the dictionary into data.
JSON String = {
«Last Name»: «Robbins»,
«First Name»: «Anthony»,
«children»: [
«Anthony's Son 1»,
«Anthony's Daughter 1»,
«Anthony's Son 2»,
«Anthony's Son 3»,
«Anthony's Daughter 2»
],
«Age»: 51
}
11.10. Десериализация нотации JSON в массивы и словари
Постановка задачи
Имеются данные в формате JSON, их необходимо десериализовать в словарь или массив.
Решение
Воспользуйтесь методом JSONObjectWithData: options: error: класса NSJSONSerialization.
Обсуждение
Если вы уже сериализовали ваш словарь или массив в объект JSON (заключенный в экземпляре NSData, см. раздел 11.9), то эти данные нужно будет десериализовать обратно в словарь или массив. Это делается с помощью метода JSONObjectWithData: options: error:, относящегося к классу NSJSONSerialization. Объект, возвращаемый этим методом, будет представлять собой либо словарь, либо массив в зависимости от того, какие данные ему были переданы. Рассмотрим пример:
/* Сейчас попытаемся сериализовать объект JSON в словарь. */
error = nil;
id jsonObject = [NSJSONSerialization
JSONObjectWithData: jsonData
options: NSJSONReadingAllowFragments
error:&error];
if (jsonObject!= nil &&
error == nil){
NSLog(@"Successfully deserialized…");
if ([jsonObject isKindOfClass: [NSDictionary class]]){
NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;
NSLog(@"Deserialized JSON Dictionary = %@", deserializedDictionary);
}
else if ([jsonObject isKindOfClass: [NSArray class]]){
NSArray *deserializedArray = (NSArray *)jsonObject;
NSLog(@"Deserialized JSON Array = %@", deserializedArray);
}
else {
/* Был возвращен какой-то другой объект. Мы не знаем,
что делать в этой ситуации, так как десериализатор
возвращает только словари или массивы. */
}
}
else if (error!= nil){
NSLog(@"An error happened while deserializing the JSON data.");
}
Если теперь объединить этот код с кодом из раздела 8.9, то можно будет сначала сериализовать словарь в объект JSON, десериализовать объект JSON обратно в словарь, а потом вывести результаты на консоль, чтобы убедиться, что все работает нормально:
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *dictionary =
@{
@"First Name": @"Anthony",
@"Last Name": @"Robbins",
@"Age": @51,
@"Children": @[
@"Anthony's Son 1",
@"Anthony's Daughter 1",
@"Anthony's Son 2",
@"Anthony's Son 3",
@"Anthony's Daughter 2",
],
};
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization
dataWithJSONObject: dictionary
options: NSJSONWritingPrettyPrinted
error:&error];
if ([jsonData length] > 0 &&
error == nil){
NSLog(@"Successfully serialized the dictionary into data.");
/* Сейчас попытаемся сериализовать объект JSON в словарь. */
error = nil;
id jsonObject = [NSJSONSerialization
JSONObjectWithData: jsonData
options: NSJSONReadingAllowFragments
error:&error];
if (jsonObject!= nil &&
error == nil){
NSLog(@"Successfully deserialized…");
if ([jsonObject isKindOfClass: [NSDictionary class]]){
NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;
NSLog(@"Deserialized JSON Dictionary = %@", deserializedDictionary);
}
else if ([jsonObject isKindOfClass: [NSArray class]]){
NSArray *deserializedArray = (NSArray *)jsonObject;
NSLog(@"Deserialized JSON Array = %@", deserializedArray);
}
else {
/* Был возвращен какой-то другой объект. Мы не знаем, что делать
в этой ситуации, так как десериализатор возвращает только словари
или массивы. */
}
}
else if (error!= nil){
NSLog(@"An error happened while deserializing the JSON data.");
}
}
else if ([jsonData length] == 0 &&
error == nil){
NSLog(@"No data was returned after serialization.");
}
else if (error!= nil){
NSLog(@"An error happened = %@", error);
}
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
// Точка переопределения для дополнительной настройки после запуска приложения
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Параметр options метода JSONObjectWithData: options: error: принимает одно или несколько следующих значений:
• NSJSONReadingMutableContainers — словарь или массив, возвращенный методом JSONObjectWithData: options: error:, будет изменяемым. Иными словами, этот метод будет возвращать либо экземпляр NSMutableArray, либо экземпляр NSMutableDictionary в противоположность изменяемому массиву или словарю;
• NSJSONReadingMutableLeaves — листовые значения будут инкапсулированы в экземпляры NSMutableString;
• NSJSONReadingAllowFragments — обеспечивает десериализацию данных JSON, чей корневой объект верхнего уровня не является массивом или словарем.
См. также
Раздел 11.9.
11.11. Включение в приложения функций социального обмена контентом