【问题标题】:Is there a way to acquire the properties from this obscure object and convert it to JSON?有没有办法从这个晦涩的对象获取属性并将其转换为 JSON?
【发布时间】:2017-07-01 19:33:36
【问题描述】:

我正在使用提供this object to me 的远程库。

如果我设置调试器,我会得到以下信息:

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 不满足可序列化的 NSMUtableArrayNSDictionary 的所有规则。

这给我留下了两个选择。一,我可以找到一些巧妙的方法将任何对象转换为 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'

【问题讨论】:

  • 这很奇怪,因为它符合KandyEventProtocol,它应该能够响应uuid(小写)和timestampeventType,根据文档。 NSLog(@"Class: %@", [event class])` 返回什么?也许[event valueForKeyPath:@"uuid"] 会返回一些东西。
  • @Larme Yours 是我一直在寻找的答案。谢谢!
  • @Larme 奇怪的是valueForKeyPathpo 一起工作,但在实际应用中却不起作用。我想知道在实时和调试环境中拥有两种不相关的方法对开发人员有什么好处。
  • 你能记录下事件的类别吗?另外,由于它是一个协议,我的猜测是它并不总是同一个类。你能检查一下[event conformsToProtocol:@protocol(KandyEventProtocol)],如果不是(这很奇怪),检查它是否尊重一个(stackoverflow.com/a/4649291/1801544
  • @Larme 返回error: cannot find protocol declaration for 'KandyEventProtocol'

标签: ios objective-c json nsjsonserialization


【解决方案1】:

所以我设法获得了所有方法的列表,如下所示:

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;

【讨论】:

    【解决方案2】:

    您说得对,因为它doesn't qualify in one or all of these ways,所以该对象可能无法序列化为 JSON。简而言之,它必须是字符串、数字和其他集合的集合,仅此而已。

    This answer suggests 一种获取属性的方法,如果你知道类的话。简而言之,它依赖于objc_property_t *properties = class_copyPropertyList(klass, &amp;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 可序列化的。如果是字典也一样。否则,如果对象是任意的,则应用自省方法来获取它的属性,为每个属性调用 getter 并回答其 json-serializable。

    【讨论】:

    • 我可能还不习惯调试器。但似乎大多数方法不在po 语法中,因为我相信如果我只编写代码并尝试运行应用程序,它们会起作用。是否有您知道的资源可以更轻松地使用此代码,而不是每次我想尝试另一段代码时都必须编译我的整个应用程序?
    • 另外.. 从链接的问题中实现该类后,什么命令将运行PropertyUtil 的代码?
    • 我认为这是一个共同的斗争。有时当我以这种方式放慢速度时,我会做一个小项目,只做我对调试感兴趣的事情。您甚至不需要外部库。只需创建一个对象,其中包含一些不序列化的内容
    • 这是一个类方法,因此您必须在添加它的任何类上调用它。它需要一个类作为参数...您可以将其作为 someId.class 发送到您的 ID
    • @Trip - 我添加了一种方法来更完整地描述递归思想。看看这是否会从你的不透明对象中生成你需要的东西。
    猜你喜欢
    • 2018-07-12
    • 2020-09-18
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多