使用 NSJSONSerialization 解析 JSON - 抛出 NSException

Posted

技术标签:

【中文标题】使用 NSJSONSerialization 解析 JSON - 抛出 NSException【英文标题】:Parsing JSON with NSJSONSerialization - NSException thrown 【发布时间】:2014-03-24 02:12:35 【问题描述】:

我正在使用NSJSONSerialization 来解析从 php 页面下拉的 JSON。以下代码用于解析 JSON 并显示数据字段的值(首先包含 JSON 示例):

"status":200,"status_message":"Book Found","data":348

代码:

- (IBAction)btnClick:(id)sender

    if(![_txtBox.text isEqual:@""])
    
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.mysite.comm/project/ws/name/%@",@"c"]]; //url for JSON

        NSError *jsonError=nil;

        NSString *jsonString = [self jsonStringWithUrl:url]; //get data as JSON

        NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; //convert to data

        NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error: &jsonError];

        _txtView.text = (NSString *)[jsonObject objectForKey:@"data"];
    

但是,代码崩溃并且我收到以下错误消息。我怀疑它与这条线有关:_txtView.text = (NSString *)[jsonObject objectForKey:@"data"]; 但我不确定要寻找什么。我是否试图以错误的方式从NSDictionary 获取数据?

2014-03-23 22:04:35.292 WebServiceTest[38975:60b] -[__NSCFNumber length]: unrecognized selector sent to instance 0x8d7f140
2014-03-23 22:04:35.296 WebServiceTest[38975:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x8d7f140'
*** First throw call stack:
(
    0   CoreFoundation                      0x017ec1e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x0156b8e5 objc_exception_throw + 44
    2   CoreFoundation                      0x01889243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x017dc50b ___forwarding___ + 1019
    4   CoreFoundation                      0x017dc0ee _CF_forwarding_prep_0 + 14
    5   Foundation                          0x011894e4 -[NSConcreteAttributedString length] + 42
    6   Foundation                          0x01188a6c -[NSConcreteAttributedString initWithString:attributes:] + 182
    7   UIKit                               0x00939e9d -[UITextView setText:] + 125
    8   WebServiceTest                      0x00002922 -[WebServiceTestViewController btnClick:] + 610
    9   libobjc.A.dylib                     0x0157d880 -[NSObject performSelector:withObject:withObject:] + 77
    10  UIKit                               0x0022d3b9 -[UIApplication sendAction:to:from:forEvent:] + 108
    11  UIKit                               0x0022d345 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
    12  UIKit                               0x0032ebd1 -[UIControl sendAction:to:forEvent:] + 66
    13  UIKit                               0x0032efc6 -[UIControl _sendActionsForEvents:withEvent:] + 577
    14  UIKit                               0x0032e243 -[UIControl touchesEnded:withEvent:] + 641
    15  UIKit                               0x0026cddd -[UIWindow _sendTouchesForEvent:] + 852
    16  UIKit                               0x0026d9d1 -[UIWindow sendEvent:] + 1117
    17  UIKit                               0x0023f5f2 -[UIApplication sendEvent:] + 242
    18  UIKit                               0x00229353 _UIApplicationHandleEventQueue + 11455
    19  CoreFoundation                      0x0177577f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    20  CoreFoundation                      0x0177510b __CFRunLoopDoSources0 + 235
    21  CoreFoundation                      0x017921ae __CFRunLoopRun + 910
    22  CoreFoundation                      0x017919d3 CFRunLoopRunSpecific + 467
    23  CoreFoundation                      0x017917eb CFRunLoopRunInMode + 123
    24  GraphicsServices                    0x037e05ee GSEventRunModal + 192
    25  GraphicsServices                    0x037e042b GSEventRun + 104
    26  UIKit                               0x0022bf9b UIApplicationMain + 1225
    27  WebServiceTest                      0x000022fd main + 141
    28  libdyld.dylib                       0x01e33701 start + 1
    29  ???                                 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

【问题讨论】:

[__NSCFNumber length]: unrecognized selector sent to instance -- 你有一个 NSNumber,你想把它当作一个 NSString。看来您的“数据”属性是一个 NSNumber。 实际上我确实在代码顶部包含了 JSON 作为注释。很抱歉造成混乱! 是的,我终于看到了。 【参考方案1】:

您显示的 JSON 对象将 348 列为整数值。因此,当NSJSONSerialization 得到它时,它会将其转换为 NSNumber。您需要在[jsonObject objectForKey:@"data"] 上调用-[NSNumber stringValue] 以将NSNumber 转换为NSString

【讨论】:

这解决了我的问题。但是,以下 JSON:"status":200,"status_message":"Book Found","data":"729" 给了我一个错误:'-[__NSCFString stringValue]: unrecognized selector sent to instance 0x1702286a0' 为什么要使用 __NSCFString 在这种情况下,“data”元素的值用引号括起来。这是一个字符串。如果您的 JSON 对象表现不佳,有时您会得到一个数字,有时是一个字符串,您可能希望将标签文本分配包裹在 if ( [[jsonObject objectForKey:@"data"] isKindOfClass:[NSString class]] ) else if ( [[jsonObject objectForKey:@"data"] isKindOfClass:[NSNumber class]] ) 类型的构造周围,以确保您始终在正确的对象上调用正确的方法,具体取决于服务器/数据源为您提供的内容。 这就是我最终所做的。这有点奇怪,但它完成了工作。谢谢!

以上是关于使用 NSJSONSerialization 解析 JSON - 抛出 NSException的主要内容,如果未能解决你的问题,请参考以下文章

NSJSONSerialization 与基于流的解析器

如何使用来自 NSString 的 NSJSONSerialization 解析 Json [重复]

iOS - 在 Swift 中使用 NSJSONSerialization 解析 JSON 字典

NSJSONSerialization 无法解析有效的 JSON - “垃圾结束”

NSJSONSerialization 不解析这个 JSON

NSJSONSerialization 不更新数据