Есть ли способ получить свойства из этого неясного объекта и преобразовать его в 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 этого.