1

I'm using PHP sockets for managing data in a chat application, here's a sample JSON string I'm expecting from the socket read :

{ "m_time" : "2015-04-07 11:37:35", "id" : "29", "msg" : "Hai there. This is a test message"}

But sometimes in the socket reads multiple objects concatenated, like this :

{ "m_time" : "2015-04-07 11:37:35", "id" : "30", "msg" : "Hai there 1"}{ "m_time" : "2015-04-07 11:37:36", "id" : "31", "msg" : "Hai there 2"}{ "m_time" : "2015-04-07 11:37:37", "id" : "32", "msg" : "Hai there 3"}

How can I json_decode no matter if there's a single object or multiple ones ?

PHP Code for Socket read:

while(@socket_recv($changed_socket, $buf, READ_SIZE, 0) >= 1)
{
    if(!$buf) logResponse('Socket Read Failed for '. $changed_socket);

    $received_text = $buf; //unmask data
    $tst_msg = json_decode($received_text); //json decode 

    logResponse('Received Data: '. $received_text);
}
// logResponse() is used to write a log file log.html
2
  • 1
    can you please show us your socket connection code? Commented Apr 7, 2015 at 6:38
  • 1
    The socket is not returning a valid JSON string in the case of multiple objects. If you want to use json_decode, this issue should be solved either by changing the socket code (preferred) or by manipulating the output you get: you need commas between }{ and you need [] at the beginning and at the end of the result. You can check JSON validity here: jsonlint.com Commented Apr 7, 2015 at 6:55

1 Answer 1

6

tidy your input, add commas after every json string, send like this:

{ "m_time" : "2015-04-07 11:37:35", "id" : "30", "msg" : "Hai there 1"},{ "m_time" : "2015-04-07 11:37:36", "id" : "31", "msg" : "Hai there 2"},{ "m_time" : "2015-04-07 11:37:37", "id" : "32", "msg" : "Hai there 3"},

php function

function json_decode_multi($s, $assoc = false, $depth = 512, $options = 0) {
    if(substr($s, -1) == ',')
        $s = substr($s, 0, -1);
    return json_decode("[$s]", $assoc, $depth, $options);
}

var_dump(json_decode_multi('{ "m_time" : "2015-04-07 11:37:35", "id" : "30", "msg" : "Hai there 1"},{ "m_time" : "2015-04-07 11:37:36", "id" : "31", "msg" : "Hai there 2"},{ "m_time" : "2015-04-07 11:37:37", "id" : "32", "msg" : "Hai there 3"},'));

output:

array(3) {
  [0] =>
  class stdClass#1 (3) {
    public $m_time =>
    string(19) "2015-04-07 11:37:35"
    public $id =>
    string(2) "30"
    public $msg =>
    string(11) "Hai there 1"
  }
  [1] =>
  class stdClass#2 (3) {
    public $m_time =>
    string(19) "2015-04-07 11:37:36"
    public $id =>
    string(2) "31"
    public $msg =>
    string(11) "Hai there 2"
  }
  [2] =>
  class stdClass#3 (3) {
    public $m_time =>
    string(19) "2015-04-07 11:37:37"
    public $id =>
    string(2) "32"
    public $msg =>
    string(11) "Hai there 3"
  }
}

Keep in mind: the protocol design is not stable. @socket_recv($changed_socket, $buf, READ_SIZE, 0) may read half a string(broken) if it meets max READ_SIZE. If the data decoding failed, you should keep the last received data, and read more data to append to it and retry.

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

1 Comment

it should work. but i think your protocol design is not stable. @socket_recv($changed_socket, $buf, READ_SIZE, 0) may read half a string(broken) if it meets max READ_SIZE. if the data decoding failed, you should keep the last received data, and read more data to append to it and retry.

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.