Сериализация iOS JSON для классов, основанных на NSObject
Я хотел бы JSON-сериализовать свои собственные пользовательские классы. Я работаю в Objective-C/iOS5.
Я хотел бы что-то сделать следующее:
Person* person = [self getPerson ]; // Any custom object, NOT based on NSDictionary
NSString* jsonRepresentation = [JsonWriter stringWithObject:person ];
Person* clone = [JsonReader objectFromJson: jsonRepresentation withClass:[Person Class]];
Кажется, что NSJSONSerialization (и несколько других библиотек) требует, чтобы класс "человек" основывался на NSDictionary и т.д. Мне нужно что-то, что будет сериализовать любой пользовательский объект, который я хочу определить (в пределах разумного).
Представьте, что Person.h выглядит так:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString* firstname;
@property NSString* surname;
@end
Я хотел бы, чтобы сгенерированный JSON для экземпляра выглядел примерно так:
{"firstname":"Jenson","surname":"Button"}
В моем приложении используется ARC. Мне нужно что-то, что будет сериализоваться и десериализоваться с помощью объектов.
Большое спасибо.
Ответы
Ответ 1
Это сложно, потому что единственные данные, которые вы можете поместить в JSON, - это прямые простые объекты (думаю, NSString, NSArray, NSNumber...), но не пользовательские классы или скалярные типы. Зачем? Без создания всех условных операторов для переноса всех этих типов данных в эти типы объектов решение будет выглядеть примерно так:
//at the top…
#import <objC/runtime.h>
NSMutableDictionary *muteDictionary = [NSMutableDictionary dictionary];
id YourClass = objc_getClass("YOURCLASSNAME");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(YourClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
SEL propertySelector = NSSelectorFromString(propertyName);
if ([classInstance respondsToSelector:propertySelector]) {
[muteDictionary setValue:[classInstance performSelector:propertySelector] forKey:propertyName];
}
}
NSError *jsonError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:muteDictionary options:0 error:&jsonError];
Это сложно, хотя из-за того, что я сказал ранее. Если у вас есть какие-либо скалярные типы или пользовательские объекты, все дело рушится. Если это действительно важно, чтобы получить что-то подобное, я бы предложил изучить время и взглянуть на ссылки Ricard, которые позволяют вам видеть типы свойств, которые будут помогать условным операторам, необходимым для переноса значений в объекты, надежные для NSDictionary.
Ответ 2
Теперь вы можете легко решить эту проблему, используя JSONModel. JSONModel - это библиотека, которая в общем случае сериализует/десериализует ваш объект на основе класса. Вы даже можете использовать не-nsobject, основанный на свойстве типа int
, short
и float
. Он также может обслуживать сложный комплекс JSON.
Пример десериализации. Обратившись к вашему примеру, в файле заголовка:
#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]);
Ответ 3
возможно, это может помочь JLObjectStrip.
это то же самое, что сказал jacob, но он повторяет даже свойство класса. это даст вам словарь/массив, а затем просто используйте sbjson/jsonkit или что вы предпочитаете строить свою json-строку.
Ответ 4
Попробуйте этот BWJSONMatcher
Это действительно просто и удобно.
...
NSString *jsonString = @"{your-json-string}";
YourValueObject *dataModel = [YourValueObject fromJSONString:jsonString];
NSDictionary *jsonObject = @{your-json-object};
YourValueObject *dataModel = [YourValueObject fromJSONObject:jsonObject];
...
YourValueObject *dataModel = instance-of-your-value-object;
NSString *jsonString = [dataModel toJSONString];
NSDictionary *jsonObject = [dataModel toJSONObject];
...
Ответ 5
Что я делаю для своих объектов, у меня есть метод под названием "toDict", который возвращает nsdictionary. В этом методе я устанавливаю все атрибуты, которые мне нужны/нужны в словаре, например
[user setObject:self.first_name forKey:@"first_name"];
[user setObject:self.last_name forKey:@"last_name"];
[user setObject:self.email forKey:@"email"];
Ответ 6
https://github.com/neildong/JLModel Это написано мной.
Преобразуйте JSON в NSObject автоматически, установите свойства в соответствии с JSON.