Сериализация iOS JSON для классов, основанных на NSObject - программирование
Подтвердить что ты не робот

Сериализация 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. Мне нужно что-то, что будет сериализоваться и десериализоваться с помощью объектов.

Большое спасибо.

4b9b3361

Ответ 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.