user3082584
user3082584

Reputation: 167

iOS parse string with multiple JSON objects?

I'm having some troubles when my app receives multiple JSON objects at the same time. I'm using a TCP socket that is open to my server which sends me messages. The reason i seem to recieve multiple messages is probably due to network lag.

This is what a server message can look like (i then put this into a NSString and try to parse the 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"
}

And here is how i currently parse the NSString, note that the above JSON is outputData in the code below:

            // 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];
            }

The above works perfectly when i only recieve one JSON in outputData but when multiple JSONs are recieved it trows an error:

PARSE ERROR ------------->>>>> : Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Garbage at end.) UserInfo=0x14e9acb0 {NSDebugDescription=Garbage at end.}

Any ideas how to handle this?

Upvotes: 0

Views: 796

Answers (4)

CouchDeveloper
CouchDeveloper

Reputation: 19116

If your data stream contains multiple JSONs in sequence, it strictly isn't JSON anymore. Rather, it is a custom protocol which embeds JSON.

You need to first define your custom protocol. It can be defined as an arbitrary number of JSONs in sequence - if this fits your needs. NSJSONSerialization isn't capable to parse your custom protocol, though.

You could define your protocol differently, for example: your data is a contiguous stream of messages, where a message is a "blob" prepended by value representing the length in bytes, e.g.:

message := message_size CRLF blob   

message_size   :=  digits

data :=   message*

That is, your data may look as follows:

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

This is of course a pretty naive protocol, but it should be sufficient to demonstrate the basic idea.

Your blob could then be JSON UTF-8.

This "protocol" can be easily parsed with a custom parser, where the "blob" (a single JSON) will be passed through a JSON parser, possibly wrapped into a NSData object.

Upvotes: 0

Vinny Coyne
Vinny Coyne

Reputation: 2365

It's erroring out because you don't have valid JSON in your string. You'll need to do something like the following to get it into the correct format:

NSString *formattedString = [NSString stringWithFormat:@"[%@]", [outputData stringByReplacingOccurrencesOfString:@"} {" withString:@"},{"]];

NSError *error = nil;
NSArray *JSON = [NSJSONSerialization JSONObjectWithData:[formattedString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];

That is assuming outputData is an NSString.

Upvotes: 0

amurcia
amurcia

Reputation: 791

Try this:

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

EDIT:

An example of JSON, because your "" can cause problems:

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

Hope it helps!

Upvotes: 0

Owen Hartnett
Owen Hartnett

Reputation: 5935

Hmm...you could wrap it yourself. Take the data you get and prepend "{ "dataarray": [" to the beginning, and "] }" to the end. This will produce an array, the elements of which will be your individual JSON entities.

Upvotes: 1

Related Questions