2012-05-09 1 views
16

я хотел бы JSON-сериализации своих собственных классов. Я работаю в Objective-C/iOS5. Я хотел бы что-то сделать следующее:IOS JSON сериализация NSObject на основе классов

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

Если вы можете получить список атрибутов, вы можете перебирать их, используя метод valueForKey: чтобы получить его содержимое и заполнить словарь ... Кажется, вы сможете сделать это с помощью class_copyPropertyList() и некоторых других странных методы. Это может помочь: http://stackoverflow.com/questions/754824/get-an-object-attributes-list-in-objective-c Удачи! –

+0

Эта ссылка помогает вам ..... [http://stackoverflow.com/a/29095726/3177007] (http://stackoverflow.com/a/29095726/3177007) –

ответ

22

Это сложный вопрос, потому что единственные данные, которые вы можете поместить в 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.

+0

спасибо за это, и спасибо Рикарду тоже , Мне удалось получить решение, построенное после вашего начального руководства. – Journeyman

+0

Отличная работа! Я надеюсь, что это не будет запрещено яблоком. – Dumoko

+0

Библиотека, предложенная Малкольмом ниже, уже делает это для вас. –

1

может быть, это может помочь JLObjectStrip.

его то же, что сказал Яаков, но он перебирает даже к свойству класса. это даст вам словарь/массив, а затем просто используйте sbjson/jsonkit или что вы предпочитаете, чтобы построить свою строку json.

14

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

Deserialize пример. Ссылаясь на вашем примере, в файле заголовка:

#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): 
} 

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

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

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

NSLog(@"%@", [person toJSONString]); 
+0

Элегантное решение. Очень признателен. –

0

Попробуйте один 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]; 
... 
0

Что я делаю для моих объектов у меня есть метод, называемый «toDict», который возвращает NSDictionary. В этом методе я установить все атрибуты мне нужно/хочу в словарь, например

[user setObject:self.first_name forKey:@"first_name"]; 
[user setObject:self.last_name forKey:@"last_name"]; 
[user setObject:self.email forKey:@"email"];