0

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?

11
  • Can you add the output of [outputData dataUsingEncoding:NSUTF8StringEncoding]? Commented Jan 17, 2014 at 15:23
  • It is unusual to get multiple JSON entities in one package. Usually the server wraps it up into one JSON array with the multiple entities being an item in the array. Can you get the server to wrap your JSON entities into a single JSON structure? Failing that, you'll have to parse out the JSON yourself and feed them to the parser one at a time. Commented Jan 17, 2014 at 15:23
  • @yoeriboven not sure i follow, what variable do you want me to echo to the console? Commented Jan 17, 2014 at 15:24
  • Try changing NSJSONReadingMutableContainers to NSJSONReadingAllowFragments Commented Jan 17, 2014 at 15:24
  • 1
    Your server returns false information, what you posted is not a valid json, it should be delimited in commas and wrapped in an array brackets [{"id":1}, {"id":2}]. You also want to assign the result into an NSAray, instead of NSDictionary. Validate your json vs jsonlint.com Commented Jan 17, 2014 at 15:31

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

You're forgetting the commas for }{ brackets
Yes, you should also look for } { and insert commas, but you should match braces and only do it at the top level.
Run a counter to increment for every { and decrement for every } and insert commas at those points where your counter goes to zero. You can convert the data to an NSMutableString and that class should give you a ton of methods for changing the contents.
How would that look in code? Not entirely sure how to write it
the simplest way is a for loop over every character. Have a variable initialized to zero. When you encounter a {, increment the variable, when you encounter a }, decrement it. When you reach zero it means you've matched the beginning {, so if you encounter after that another {, then insert a comma first.
0

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!

Comments

0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.