Сериализация сложного объекта NSObject to JSON - PullRequest
2 голосов
/ 08 февраля 2012

У меня есть серия NSObject, которые я хотел бы сериализовать в JSON и опубликовать в сервисе. Конечный объект состоит из нескольких уровней этих подклассов NSObject, вложенных друг в друга.

Каждый из этих объектов следует протоколу с методом, который возвращает свойства этих объектов в NSDictionary с соответствующими ключами. Однако некоторые из этих свойств являются другими объектами и т. Д., Что делает сериализацию немного сложной.

Можно ли использовать шаблон, чтобы упростить сериализацию конечного объекта? Используя JSONKit, кажется, мне нужно было бы сериализовать каждый словарь отдельно от самого глубокого объекта и работать в обратном направлении, проверяя ошибки, а затем добавляя в составную строку. Я знаю, что это не может быть лучшим методом с использованием этой очень способной библиотеки. Любое предложение или руководство приветствуется.

Редактировать 1

JSONKit GitHub URL

Документация по JSONKit Readme

Ответы [ 3 ]

8 голосов
/ 08 февраля 2012

Библиотека AutomagicCoding использует низкоуровневый самоанализ свойств для рекурсивного преобразования любого объекта NSO в NSDictionary, который затем может быть напрямую сериализован в виде JSON:

https://github.com/psineur/NSObject-AutomagicCoding

Может потребоваться немноготонкой настройки для классов со свойствами, которые являются структурами и т. д., но это, вероятно, самый простой и наименее трудоемкий подход, который вы найдете.

ОБНОВЛЕНИЕ:

С тех пор я написал свойсобственная библиотека, HRCoding (https://github.com/nicklockwood/HRCoder), которая может загружать / сохранять любой объект как JSON с использованием протокола NSCoding)

2 голосов
/ 27 мая 2013

Теперь вы можете легко решить эту проблему, используя JSONModel . JSONModel - это библиотека, которая обобщенно сериализует / десериализует ваш объект на основе Class. Вы даже можете использовать не-nsobject для таких свойств, как int, short и float. Он также может обслуживать вложенный комплекс JSON. Он обрабатывает проверку ошибок для вас.

Учитывая это JSON {"firstname":"Jenson","surname":"Button"}

Пример десериализации . в заголовочном файле:

#import "JSONModel.h"

@interface Person : JSONModel 
@property (nonatomic, strong) NSString* firstname;
@property (nonatomic, strong) NSString* surname;
@end

в файле реализации:

#import "JSONModelLib.h"
#import "yourPersonClass.h"

NSString *responseJSON = /*from somewhere*/;
Person *person = [[Person alloc] initWithString:responseJSON error:&err];
if (!err)
{
   NSLog(@"%@  %@", person.firstname, person.surname):
}

Пример сериализации . В файле реализации:

#import "JSONModelLib.h"
#import "yourPersonClass.h"

Person *person = [[Person alloc] init];
person.firstname = @"Jenson";
person.surname = @"Uee";

NSLog(@"%@", [person toJSONString]);
1 голос
/ 08 февраля 2012

Я не уверен, что понимаю проблему. Вы просите образец, но, кажется, описываете стандартный:

Каждый из этих объектов следует протоколу с методом, который возвращает свойства этих объектов в NSDictionary с соответствующими ключами.

Допустим, этот метод называется serializedDictionary. Если у класса есть свойства, которые сами являются другими объектами, вы просто вызываете serializedDictionary и добавляете результат в созданный вами словарь. Поэтому все, что вам нужно сделать, это запросить у объекта верхнего уровня serializedDictionary и преобразовать его в JSON.

Если вы беспокоитесь об обработке ошибок, просто проверьте результат метода и передайте ошибку своему вызывающему. Вы можете сделать это с исключениями (без кода для записи) или по соглашению. Например, при ошибке вы возвращаете nil, а также посредством ссылки на указатель на экземпляр NSError. Затем в ваших контейнерах вы делаете что-то вроде этого:

- (NSDictionary *)serializedDictionaryWithError:(NSError **)error
{
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:self.someProperty forKey:@"some-property"];
    NSDictionary *childDict = [self.childObject serializedDictionaryWithError:error];
    if (childDict == nil) return nil;
    [dict setObject:childDict forKey:@"child-object"];
    return dict;
}

Bamn!

...