2

Let simplify the question:

All I need is to explode() string by a comma between brackets. The problem is that elements selected by comma can have a comma in itself, thus simple exploding won't work. I am not asking how to decode JSON.

The number of arguments, their type will always be different, e.g.

('foo')
('bar', NULL)
({"JSON": "data"}, 'test')

Assuming that I have this part of the code:

({"class": "navigation", "id": "navigation"}, NULL, 'bar' /* [..] */)

Can anyone suggest a regex (or alternative method) to get all the comma separated entries (as string)? The problem is that variables can contain commas in itself. Thus, I assume this requires recursion.

Expected result would be an array containing following entries:

{"class": "navigation", "id": "navigation"}
NULL
'bar'
j0k
  • 21,914
  • 28
  • 75
  • 84
Gajus
  • 55,791
  • 58
  • 236
  • 384
  • What are the rules here? Is this any piece of PHP code? Can strings and comments contain anything? What about other features: `{'Peoples\' names':['a', 2, getThird("1", {"q":5})]} // , 6` (I don't know enough PHP to come up with scary stuff, but I know it has weird string literals, for one). If it's real PHP, your best bet is to find a parser. – Kobi Mar 01 '11 at 19:51

5 Answers5

2

After many hours of work, I have come across that PHP will fail to parse JSON string containing NULL (uppercase null). That was what caused the following code not to work. However, simply replacing NULL to null solved the problem.

var_dump(json_decode('[{"class": "navigation", "id": "navigation"}, NULL, "bar"]')
Gajus
  • 55,791
  • 58
  • 236
  • 384
2

Here's something that works:

$str = 'NULL, {"class": "navigation", "id": "navigation"}, NULL, \'bar\'';
var_dump(preg_split( '%(,(?!.*})|,(?=.*{)\s+)%', $str));

Result:

~$ php ./test.php
array(4) {
  [0]=>
  string(4) "NULL"
  [1]=>
  string(44) "{"class": "navigation", "id": "navigation"}"
  [2]=>
  string(5) "NULL"
  [3]=>
  string(6) "'bar'"
}

Not exactly a recursive regex, but rather a look ahead assertion. The condition is that comma should not be followed by }, or it should be followed by {.

Sergey
  • 1,151
  • 7
  • 16
0

Add that code between [ and ], and use json_decode()

It should return an associative array

You should use [] for implicit indexes and {} for explicit indexes

Example:

[] : ['w', null, 123, {'a':1}] <- implicit keys (0, 1, 2, 3)
{} : {'0':'w', '1':null, '2':123, '3':{'a':1}} <- explicit keys (0, 1, 2, 3)

  You can not mix implicit/explicit indexes into the same structure, but you can for example, create an array ([]) containing different values as shown in the examples above.

$code = substr('({"id":"navigation"}, null, "bar")', 1, -1); // removes ^\( and \)$
$result = json_decode('[' . $code . ']');

echo $result[0]['id']; // returns 'navigation'
echo $result[1]; // returns NULL
echo $result[2]; // returns 'bar'
w35l3y
  • 7,389
  • 2
  • 35
  • 49
  • This is not enough, because json_decode('{"best":"mest", "best"}') would return NULL – Gajus Feb 27 '11 at 15:51
  • you forgot the [ and ], and that string you mentioned is an invalid json – w35l3y Feb 27 '11 at 15:53
  • `["foo"]` would work, but `["test":"best", "best"]` would fail. Either it is invalid or not, I need it to work. – Gajus Feb 27 '11 at 16:06
  • 1
    then change the example in your question because this one differs from the ones in your question. – w35l3y Feb 27 '11 at 16:12
0

That looks like json. You should use json_decode, which will create an array, then you can loop through the array to get the key/values.

Brent Baisley
  • 12,441
  • 2
  • 21
  • 39
0

hack alert!

  1. wrap {} into single quotes, so that your {"JSON": "data"} becomes '{"JSON": "data"}'

  2. use str_getcsv() to parse a string (it's a CSV now)

  3. go though resulting array and strip single quotes from {}

beklip
  • 98
  • 1
  • 5
  • This seemed like a smart approach, though it is not, since: `{"class": "navigation", "id": "navigation"}, NULL, 'bar'` will return `{"class": "navigation"` as one element and `"id": "navigation"},` as another. – Gajus Feb 27 '11 at 16:05
  • @Guy ok, but the first step would convert {"class": "navigation", "id": "navigation"}, NULL, 'bar' into '{"class": "navigation", "id": "navigation"}', NULL, 'bar', so that JSON bit becomes a single value (in CSV terms) – beklip Feb 27 '11 at 16:16