views:

198

answers:

8

I've a string which looks like this:

[{text:"key 1",value:"value 1"},{text:"key 2",value:"value 2"},{text:"key 3",value:"value 3"}]

I'm not sure what kind of notation this is, AFAIK this is generated by a ASP .NET backend. It looks a lot similar to JSON but calling json_decode() on this fails.

Can someone bring me some light on this kind of notation and provide me a efficient way to parse it into a key / value array with PHP?

A: 

It looks like javascript syntax (similar to JSON). Regular expressions are the way to go for parsing it. Strip the '[' and ']', then separate on the ','. Then parse each object individually.

John Fisher
The problem rises when a string contains a comma.
giorgian
Separate on },{ like I point out below in my answer.
Will Bickford
Regular expressions can handle quoted strings containing commas. I've done it quite a few times.
John Fisher
+2  A: 

It is JSON-like, but apparently not exactly to the spec. The PHP json_decode function only likes double quoted key names:

// the following strings are valid JavaScript but not valid JSON

// the name and value must be enclosed in double quotes
// single quotes are not valid 
$bad_json = "{ 'bar': 'baz' }";
json_decode($bad_json); // null

// the name must be enclosed in double quotes
$bad_json = '{ bar: "baz" }';
json_decode($bad_json); // null

// trailing commas are not allowed
$bad_json = '{ bar: "baz", }';
json_decode($bad_json); // null
nickf
A: 

I have never used it, but maybe give a look at json_decode.

giorgian
did you *read* the question?
nickf
gosh, you're right. I think I shouldn't try to answer questions at this hour.
giorgian
+2  A: 

Any way you can change the output? Quoting the key names seems to allow it to parse normally:

    $test = '[{"text":"key 1","value":"value 1"},{"text":"key 2","value":"value 2"},{"text":"key 3","value":"value 3"}]';

    var_dump(json_decode($test));
Typeoneerror
I guess I could str_replace the text: and value: and enclose them in double quotes.
Alix Axel
A: 

It looks like a custom format. Replace the [{ and }] delimiters at the beginning and the end. Then explode on "},{" and you get this:

text:"key 1",value:"value 1"
text:"key 2",value:"value 2"
text:"key 3",value:"value 3"

At that point you can iterate over each element in the array and use preg_match to extract your values.

Will Bickford
Technically there's no reason a string couldn't contain a `},{` ... even if it is much less likely than a string containing a `,`
Daniel LeCheminant
The reason I chose to explode on },{ is because , definitely appears in the sample output as a delimiter between values within a field block. But yes I agree.
Will Bickford
A: 

It looks almost like a sort of array-style data container - text being the index and value being the value.

$string = ....;
$endArray = array()
$string = trim($string,'[]');
$startArray = preg_split('/{.+}/'); 
// Array of {text:"key 1",value:"value 1"}, this will also skip empty conainers
foreach( $startArray as $arrayItem ) {
  $tmpString = trim($arrayItem,'{}');  // $tmp = text:"key 1",value:"value 1"
  $tmpArray = explode(',',$tmpString); // $tmpArray = ('text: "key 1"', 'value: "value 1"')
 $endArray[substr($tmpArray[0],7,strlen($tmpArray[0])-1)] = substr($tmpArray[1],7,strlen($tmpArray[1])-1);
}
Robert DeBoer
A: 

To get your JSON data accepted by json_decode(), you could use the following regular expression:

function json_replacer($match) {
  if ($match[0] == '"' || $match[0] == "'") {
    return $match;
  }
  else {
    return '"'.$match.'"';
  }
}

$json_re = <<<'END'
/ " (?: \\. | [^\\"] )* "     # double-quoted string, with escapes
| ' (?: \\. | [^\\'] )* '     # single-quoted string, with escapes
| \b [A-Za-z_] \w* (?=\s*:)   # A single word  followed by a colon
/x
END;

$json = preg_replace_callback($json_re, 'json_replacer', $json);

Because the matches will never overlap, a word followed by colon inside a string will never match.


I also found a comparison between different JSON implementations for PHP:

http://gggeek.altervista.org/sw/article_20061113.html

MizardX
+1  A: 

That sample is valid YAML, which is a superset of JSON. There seem to be at least 3 PHP libraries for YAML.

If it is in fact YAML, you're better off using a real YAML library, than running it through a regex and throwing it at your JSON library. YAML has support for other features (besides unquoted strings) which, if your ASP.NET backend uses, aren't going to survive the trip.

Alec