【问题标题】:iOS parse string with multiple JSON objects?iOS用多个JSON对象解析字符串?
【发布时间】:2014-01-18 19:20:23
【问题描述】:

当我的应用同时接收多个 JSON 对象时,我遇到了一些麻烦。我正在使用一个对我的服务器开放的 TCP 套接字,它向我发送消息。我似乎收到多条消息的原因可能是由于网络滞后。

这是服务器消息的样子(然后我将其放入 NSString 并尝试解析 JSON):

{
    "id": "156806",
    "type": "message",
    "userCity": "",
    "userCountry": "",
    "os": "",
    "browser": "",
    "trafficType": "",
    "seKeyword": "",
    "seType": "",
    "currentPage": "",
    "userId": "1",
    "agentId": "352",
    "customField1": "",
    "visitorNick": "Visitor 147220060",
    "msg": "asd",
    "time": "16:05",
    "channel": "V147220060",
    "visits": "254"
} {
    "type": "previewStopped",
    "msg": "",
    "visitorNick": "Mackan",
    "customField1": "",
    "visitorNick": "Visitor V147220060",
    "time": "16:05",
    "channel": "V147220060"
} {
    "id": "156807",
    "type": "message",
    "userCity": "",
    "userCountry": "",
    "os": "",
    "browser": "",
    "trafficType": "",
    "seKeyword": "",
    "seType": "",
    "currentPage": "",
    "userId": "1",
    "agentId": "352",
    "customField1": "",
    "visitorNick": "Visitor 147220060",
    "msg": "as",
    "time": "16:05",
    "channel": "V147220060",
    "visits": "254"
} {
    "id": "156808",
    "type": "message",
    "userCity": "",
    "userCountry": "",
    "os": "",
    "browser": "",
    "trafficType": "",
    "seKeyword": "",
    "seType": "",
    "currentPage": "",
    "userId": "1",
    "agentId": "352",
    "customField1": "",
    "visitorNick": "Visitor 147220060",
    "msg": "da",
    "time": "16:05",
    "channel": "V147220060",
    "visits": "254"
}

这是我目前解析 NSString 的方式,请注意上面的 JSON 在下面的代码中是 outputData

            // Parse the message from the server
            NSError* error;
            NSDictionary *JSON =
            [NSJSONSerialization JSONObjectWithData: [outputData dataUsingEncoding:NSUTF8StringEncoding]
                                            options: NSJSONReadingMutableContainers
                                              error: &error];


            NSString* type = [JSON objectForKey:@"type"];

            if(error) {
                NSLog(@"PARSE ERROR ------------->>>>> : %@\n", error);
            }

            NSLog(@"SERVER TYPE --> %@\n", type);

            if([type isEqualToString:@"message"]) {                    
                [self messageReceived:outputData];
            }

当我在outputData 中只收到一个 JSON 时,上述方法非常有效,但是当收到多个 JSON 时,它会引发错误:

解析错误 ------------->>>>> : 错误域=NSCocoaErrorDomain Code=3840 “操作无法完成。(Cocoa 错误 3840。)” (最后的垃圾。) UserInfo=0x14e9acb0 {NSDebugDescription=垃圾在 结束。}

任何想法如何处理这个?

【问题讨论】:

  • 可以添加[outputData dataUsingEncoding:NSUTF8StringEncoding]的输出吗?
  • 在一个包中获取多个 JSON 实体是不寻常的。通常,服务器将其包装成一个 JSON 数组,其中多个实体是数组中的一项。你能让服务器把你的 JSON 实体包装成一个单一的 JSON 结构吗?如果做不到这一点,您将不得不自己解析 JSON 并一次将它们提供给解析器。
  • @yoeriboven 不确定我是否关注,您希望我向控制台回显什么变量?
  • 尝试将NSJSONReadingMutableContainers更改为NSJSONReadingAllowFragments
  • 您的服务器返回错误信息,您发布的不是有效的json,应以逗号分隔并包裹在数组括号中 [{"id":1}, {"id":2 }]。您还希望将结果分配给 NSAray,而不是 NSDictionary。验证您的 json 与 jsonlint.com

标签: ios objective-c


【解决方案1】:

嗯……你可以自己包起来。获取您获得的数据并将"{ "dataarray": [" 放在开头,将"] }" 放在结尾。这将生成一个数组,其中的元素将是您的个人 JSON 实体。

【讨论】:

  • 您忘记了 }{ 括号的逗号
  • 是的,您还应该查找 } { 并插入逗号,但您应该匹配大括号并且只在顶层进行。
  • 运行一个计数器,为每个 { 递增,为每个 } 递减,并在计数器变为零的点插入逗号。您可以将数据转换为 NSMutableString,该类应该为您提供大量更改内容的方法。
  • 这在代码中看起来如何?不完全确定如何写
  • 最简单的方法是对每个字符进行 for 循环。将变量初始化为零。当你遇到 { 时,增加变量,当你遇到 } 时,减少它。当你到达零时,意味着你已经匹配了开头的 {,所以如果你在之后遇到另一个 {,那么先插入一个逗号。
【解决方案2】:

试试这个:

NSData *jsonData = [outputData dataUsingEncoding:NSUTF8StringEncoding];
NSArray *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&e];
NSDictionary *JSON = [dict objectAtIndex:0];
NSString* type = [JSON objectForKey:@"type"];

编辑:

JSON 的一个例子,因为你的 "" 可能会导致问题:

{
    aula = "AULA M04";
    cuatrimestre = "Primer quadrimestre";
    dia = Dimecres;
    edificio = "AULARI V";
    fin = "18:00";
    inicio = "15:00";
}

希望对你有帮助!

【讨论】:

    【解决方案3】:

    出错是因为您的字符串中没有有效的 JSON。您需要执行以下操作才能将其转换为正确的格式:

    NSString *formattedString = [NSString stringWithFormat:@"[%@]", [outputData stringByReplacingOccurrencesOfString:@"} {" withString:@"},{"]];
    
    NSError *error = nil;
    NSArray *JSON = [NSJSONSerialization JSONObjectWithData:[formattedString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
    

    假设outputDataNSString

    【讨论】:

      【解决方案4】:

      如果您的数据流按顺序包含多个 JSON,那么严格来说它不再是 JSON。相反,它是一个嵌入 JSON 的 自定义 协议。

      您需要首先定义您的自定义协议。它可以按顺序定义为任意数量的 JSON - 如果这符合您的需要。不过,NSJSONSerialization 无法解析您的 custom 协议。

      您可以不同地定义您的协议,例如:您的数据是一个连续的消息流,其中消息是一个“blob”,前面带有表示字节长度的值,例如:

      message := message_size CRLF blob   
      
      message_size   :=  digits
      
      data :=   message*
      

      也就是说,您的数据可能如下所示:

      2\n\r[]4\n\r5["a"]
      

      这当然是一个非常幼稚的协议,但它应该足以展示基本思想。

      然后您的 blob 可能是 JSON UTF-8。

      可以使用自定义解析器轻松解析此“协议”,其中“blob”(单个 JSON)将通过 JSON 解析器传递,可能包装到 NSData 对象中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-13
        • 2023-03-07
        • 1970-01-01
        • 2019-11-27
        • 1970-01-01
        • 2013-03-12
        • 1970-01-01
        相关资源
        最近更新 更多