我有一个包含javascript对象序列化的PHP字符串:
$string = '{fu:"bar",baz:["bat"]}';
当然,实际字符串要复杂得多,但仍是格式良好的JavaScript。这不是标准JSON,因此json_decode会失败。您知道任何能解析此字符串并返回php关联数组的php库吗?
我有一个包含javascript对象序列化的PHP字符串:
$string = '{fu:"bar",baz:["bat"]}';
当然,实际字符串要复杂得多,但仍是格式良好的JavaScript。这不是标准JSON,因此json_decode会失败。您知道任何能解析此字符串并返回php关联数组的php库吗?
class JsParserException extends Exception {}
function parse_jsobj($str, &$data) {
$str = trim($str);
if(strlen($str) < 1) return;
if($str{0} != '{') {
throw new JsParserException('The given string is not a JS object');
}
$str = substr($str, 1);
/* While we have data, and it's not the end of this dict (the comma is needed for nested dicts) */
while(strlen($str) && $str{0} != '}' && $str{0} != ',') {
/* find the key */
if($str{0} == "'" || $str{0} == '"') {
/* quoted key */
list($str, $key) = parse_jsdata($str, ':');
} else {
$match = null;
/* unquoted key */
if(!preg_match('/^\s*[a-zA-z_][a-zA-Z_\d]*\s*:/', $str, $match)) {
throw new JsParserException('Invalid key ("'.$str.'")');
}
$key = $match[0];
$str = substr($str, strlen($key));
$key = trim(substr($key, 0, -1)); /* discard the ':' */
}
list($str, $data[$key]) = parse_jsdata($str, '}');
}
"Finshed dict. Str: '$str'\n";
return substr($str, 1);
}
function comma_or_term_pos($str, $term) {
$cpos = strpos($str, ',');
$tpos = strpos($str, $term);
if($cpos === false && $tpos === false) {
throw new JsParserException('unterminated dict or array');
} else if($cpos === false) {
return $tpos;
} else if($tpos === false) {
return $cpos;
}
return min($tpos, $cpos);
}
function parse_jsdata($str, $term="}") {
$str = trim($str);
if(is_numeric($str{0}."0")) {
/* a number (int or float) */
$newpos = comma_or_term_pos($str, $term);
$num = trim(substr($str, 0, $newpos));
$str = substr($str, $newpos+1); /* discard num and comma */
if(!is_numeric($num)) {
throw new JsParserException('OOPSIE while parsing number: "'.$num.'"');
}
return array(trim($str), $num+0);
} else if($str{0} == '"' || $str{0} == "'") {
/* string */
$q = $str{0};
$offset = 1;
do {
$pos = strpos($str, $q, $offset);
$offset = $pos;
} while($str{$pos-1} == '\\'); /* find un-escaped quote */
$data = substr($str, 1, $pos-1);
$str = substr($str, $pos);
$pos = comma_or_term_pos($str, $term);
$str = substr($str, $pos+1);
return array(trim($str), $data);
} else if($str{0} == '{') {
/* dict */
$data = array();
$str = parse_jsobj($str, $data);
return array($str, $data);
} else if($str{0} == '[') {
/* array */
$arr = array();
$str = substr($str, 1);
while(strlen($str) && $str{0} != $term && $str{0} != ',') {
$val = null;
list($str, $val) = parse_jsdata($str, ']');
$arr[] = $val;
$str = trim($str);
}
$str = trim(substr($str, 1));
return array($str, $arr);
} else if(stripos($str, 'true') === 0) {
/* true */
$pos = comma_or_term_pos($str, $term);
$str = substr($str, $pos+1); /* discard terminator */
return array(trim($str), true);
} else if(stripos($str, 'false') === 0) {
/* false */
$pos = comma_or_term_pos($str, $term);
$str = substr($str, $pos+1); /* discard terminator */
return array(trim($str), false);
} else if(stripos($str, 'null') === 0) {
/* null */
$pos = comma_or_term_pos($str, $term);
$str = substr($str, $pos+1); /* discard terminator */
return array(trim($str), null);
} else if(strpos($str, 'undefined') === 0) {
/* null */
$pos = comma_or_term_pos($str, $term);
$str = substr($str, $pos+1); /* discard terminator */
return array(trim($str), null);
} else {
throw new JsParserException('Cannot figure out how to parse "'.$str.'" (term is '.$term.')');
}
}
使用方法:
$data = '{fu:"bar",baz:["bat"]}';
$parsed = array();
parse_jsobj($data, $parsed);
var_export($parsed);
提供:
array (
'fu' => 'bar',
'baz' =>
array (
0 => 'bat',
),
)
使用以下字符串进行测试:
'{fu:"bar",baz:["bat"]}',
'{rec:{rec:{rec:false}}}',
'{foo:[1,2,[3,4]]}',
'{fu:{fu:"bar"},bar:{fu:"bar"}}',
'{"quoted key":[1,2,3]}',
'{und:undefined,"baz":[1,2,"3"]}',
'{arr:["a","b"],"baz":"foo","gar":{"faz":false,t:"2"},f:false}',
[
开头。例如:[5,4,3,'too',"Juan"]
。 - Jesse Chisholm},
时,它似乎认为它已经完成了(过早地)。而且由于某种原因,递归太深会导致它抛出无效键错误,并且引号等方面对齐不正确?但还是感谢提供起点。 - Tustin2121{key:[{id:1,price:1000,commnet:"foo",memo:[]},{id:2,price:2000,memo:[]}]}
时,出现了错误。因此,我开发了一个库来解决这个问题。所有测试字符串都已通过。我希望它对每个人都有用。https://github.com/Osushi/jsobj2php - Osushi感谢luttkens。
Yii框架的CJSON::decode()
类完美运行!
最初的回答已经能够满足需求。
require_once ($_SERVER['DOCUMENT_ROOT']."/phplib/CJSON.php");
$json = new CJSON();
$data = $json->decode('{ url : "/jslib/maps/marker/marker_red.png", height : 34, width : 20, anchorIcon : [5,25.5], anchorText : [0,2], }', true);
print_r( $data );
result :
Array
(
[url] => /jslib/maps/marker/marker_red.png
[height] => 34
[width] => 20
[anchorIcon] => Array
(
[0] => 5
[1] => 25.5
)
[anchorText] => Array
(
[0] => 0
[1] => 2
)
)
<?php
function jsObjectToJSON($objstring)
{
$objstring = preg_replace('/(\w+):/i', '"$1":', $objstring); // replace key with "key"
$objstring = preg_replace('/\'/i', '"', $objstring); // replace ' with "
return $objstring;
}
// usage
$objstring = '{foo: "bar", baz: "qux"}';
$json = jsObjectToJSON($objstring);
echo $json; // {"foo": "bar", "baz": "qux"}
// now you can use json_decode() on the result
var_dump(json_decode($json, true));
// array(2) {
// ["foo"]=>
// string(3) "bar"
// ["baz"]=>
// string(3) "qux"
// }
$evaluation = $page->callFunction(
"function(a, b) {\n window.foo = '{fu:\"bar\",baz:[\"bat\"]}';\n}",
[1, 2]
);
$value = $evaluation->getReturnValue();