views:

80

answers:

3

For example I have this string of 2 json objects:

{"glossary": {"title": "example glossary"}, "aaa": "1212"}{"adada": "faka"}

I want to split it in the array for PHP and Actionscript 3

Array ( 
[0] => '{"glossary": {"title": "example glossary"}', 
[1] => '{"adada": "faka"}' 
)

What is the best method to do it.

Edit:

I don't need answer how to parse json. To simplify I need to split

{...{..}....}{....}{........}

into

{...{..}....}

{....}

{........}

+1  A: 

Regex is not the right tool for this - use a JSON Parser

Amarghosh
+1, but JSON parser is not the right approach either, since the input is not valid JSON. one could modify the corelib parser to somehow get the values.
back2dos
I don't need to know how to parse. I want to know how to split it. I think it can be only simple regex, but regex is not my strong side.
kasp3r
@kasp3r: regex simply is not capable of expressing JSON grammar, unless you want infintely big regexes.
back2dos
+1  A: 

either you modify a JSON parser to do it, as Amargosh suggested, or you can make a simple algorithm to do it for you, that skipps through strings and comments and keeps track of open braces. when no open braces are left, then you have a complete value. repeat it until you're out of input.

however my suggestion is to try to solve the problem by talking to whoever is responsible for that output and convince him to generate valid JSON, which is [{"glossary": {"title": "example glossary"}, "aaa": "1212"},{"adada": "faka"}]

edit: to separate the JSON objects, you need to prefix every JSON object with a length (4 byte should suffice). then you read off the socket until you have the right amount of chars. the next characters will again be the length of the next object. it is imperative that you do this, because TCP works in packets. Not only can you have multiple JSON-objects in one single packet, but you can have one JSON-object split between two packets.

Also, a couple of advises:

  • do not use PHP for socket servers. it's not made for that. have a look at haXe, specifically the neko backend.
  • do not write this kind of stuff on your own unless you really need to. it's boring and dumb work. there are virtually millions of solutions for socket servers. you should also have a look at haXe remoting that allows transparent communication between e.g. a flash client and a neko socket server. also, please have a look at smartfox and red5.

edit2: you're underestimating the problem and your approach isn't good. you should build a robust solution, so the day you want to send arrays over the wire you won't have a total breakdown, because your "splitter" breaks, or your JSON parser is fed incomplete objects, because only half the object is read. what you want to do can be easily done: split the input using "}{", append "}" to any element but the last and prepend "{" to any element but the first. Nonetheless I heavily suggest you refrain from such an approach, because you will regret it at some point. if you really think you should do thinks like these on your own, then try to at least do them right.

greetz
back2dos

back2dos
I need to split it, because I am writing a php sockets server and somehow sometimes in one buffer I get 2 json (merges for some reason, and it happens when I try to send few commands fast at the same time).
kasp3r
@kasp3r: please see my update.
back2dos
A: 

Regex can't handle it. If you don't actually need a JSON parser, writing a simple parsing function should do it.

Something like this would do:

function splitJSONString($json) {
    $objects = array();

    $depth = 0;
    $current = '';

    for ($i = 0; $char = substr($json, $i, 1); $i++) {
        $current .= $char;

        if ($char == '{') {
            $depth += 1;
        } else if ($char == '}' && $depth > 0) {
            $depth -= 1;

            if ($depth == 0) {
                array_push($objects, $current);
                $current = '';
            }
        }           
    }

    return $objects;
}
MrKishi
please see my answer for details on a proper JSON scanner. This one will fail in many cases. examples: null, 5, true, "test", [], { "}":"foo"}.
back2dos
@back2dos Agreed, completely.
MrKishi