Есть ли способ получить свойства из этого неясного объекта и преобразовать его в JSON?

Я работаю с удаленной библиотекой, которая доставляет мне этот объект.

Если я установлю свой отладчик, я получу эту информацию:

KandyChatMessage: UUID - 70886A79-2FF60F5E1A3961EF , timestamp - 2017-02-13 17:46:12 +0000 , sender - uri - 3@domain.domain.com, userName - 3, domain - domain.domain.com, type - 0, associationType - 1 , recipient - uri - afdab3bfb5774@domain.domain.com, userName - afdab3bfb57a12b5, domain - domain.domain.com, type - 1, associationType - 1 , type: - 1 , mediaItem - KandyTextMessageData - text:3 , info:(null) , isIncoming - 1 , additionalData - (null), fromHistory - NO

Поставляется с помощью этого метода:

-(void)_addEventAndRefresh:(id<KandyEventProtocol>)event{

Цель состоит в том, чтобы преобразовать этот объект в JSON примерно так:

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:event
                                                   options:0
                                                     error:&error];

Тем не менее, это вылетает мое приложение, так как я предполагаю, что event не соответствует всем правилам сериализуемого NSMUtableArray или NSDictionary по какой-то причине.

Это оставляет мне два варианта. Во-первых, я могу найти какой-то хитрый метод для преобразования любого объекта в JSON. Или два, я могу выбрать эти данные и написать объект NSDictionary с нуля.

Кто-нибудь имел бы хоть малейшее представление о том, как отделить этот тип объекта?

В моем debuggerкажется, он ни на что не реагирует..

> po event.UUID
=> error: property 'UUID' not found on object of type 'id'
> po event.timestamp
=> error: property 'timestamp' not found on object of type 'id'

2 ответа

Решение

Итак, мне удалось получить список всех методов, например, так:

int i=0; unsigned int mc = 0; 
Method * mlist = class_copyMethodList(event, &mc); 
NSLog(@"%d methods", mc); for(i=0;i<mc;i++)     
NSLog(@"Method no #%d: %s", i, sel_getName(method_getName(mlist[i])));

И тогда я понял, что должен был класс отлить объект, чтобы получить его элементы:

KandyChatMessage *chatMessage = (KandyChatMessage*)event;
chatMessage.description;

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

Этот ответ предлагает способ получить свойства, если вы знаете класс. В двух словах, он опирается на objc_property_t *properties = class_copyPropertyList(klass, &outCount); чтобы получить свойства.

Вы можете использовать это, чтобы получить сериализуемые свойства JSON объекта, поместив их значения (с указанием их имени) в словарь. Затем JSON сериализует это.

РЕДАКТИРОВАТЬ Чтобы продемонстрировать, я добавил этот метод в класс PropertyUtil, предложенный этим другим ответом...

+ (id)jsonSerializableFromObject:(id)object {
    if ([object isKindOfClass:[NSString self]] ||
        [object isKindOfClass:[NSNumber self]] ||
        [object isKindOfClass:[NSNull self]]) {
        return object;
    } else if ([object isKindOfClass:[NSArray self]]) {
        NSMutableArray *result = [NSMutableArray array];
        for (id e in (NSArray *)object) {
            id element = [self jsonSerializableFromObject:e];
            [result addObject:element];
        }
        return result;
    } else if ([object isKindOfClass:[NSArray self]]) {
        NSMutableDictionary *result = [NSMutableDictionary dictionary];
        for (id key in [(NSDictionary *)object allKeys])
            result[key] = [self jsonSerializableFromObject:(NSDictionary *)object[key]];
        return result;
    } else {
        NSMutableDictionary *result = [NSMutableDictionary dictionary];
        NSDictionary *props = [PropertyUtil classPropsFor:[object class]];
        for (NSString *propName in [props allKeys]) {
            id value = [object performSelector:NSSelectorFromString(propName)];
            result[propName] = [self jsonSerializableFromObject:value];
        }
        return (result.count)? result : [NSNull null];
    }
}

Просто быстрый набросок: если операнд можно сериализовать в JSON, верните его. Если операндом является массив, ответьте на массив каждого элемента, сделанный json-сериализуемым. То же самое, если это словарь. В противном случае, если объект является чем-то произвольным, примените метод интроспекции, чтобы получить его свойства, вызовите метод получения для каждого свойства и ответьте на json-serializable этого.

Другие вопросы по тегам