开发者

Handling malformed JSON in PHP

I'm trying to write a php script that handles data from a webservice that delivers "json" as a string. The problem is the string isn't really json; it's javascript. Specifically, the keys are not quoted, although the variables are. Example (the actual data is much longer and more complicated):

{de开发者_开发技巧sc:'User defined payload'}

As described by the php manual, json_decode() correctly fails to interpret this string.

My question is, how can I successfully interpret a string like this in php?

The only solution I can think of is to write some regular expressions that fix the syntax, but then I'd have two problems.

EDIT

Hadvig's suggestion of using the Services_JSON pear module worked, and looks like a general solution. Once I had the module installed, my code looked like this:

require_once 'PEAR.php';
require_once 'Services/JSON.php';

$Services_JSON = new Services_JSON();
$data = $Services_JSON->decode($malformed_json);

Unfortunately, this is SLOW. To interpret the whole string (~400,000 chars) took > 36 seconds! Using a regular expression to fix the quotes and then using json_decode took ~0.04 seconds. Here's what I used:

// fix single quotes
$s = str_replace("'", '"', $malformed_json);

// fix unquoted keys
$valid_json = preg_replace('/([{\[,])\s*([a-zA-Z0-9_]+?):/', '$1"$2":', $s);

$data = json_decode($valid_json);

Of course, this will break if the data contains any quotes, brackets, or commas.


Ok. try to use this. http://pear.php.net/pepr/pepr-proposal-show.php?id=198 I just check your string


Depends on how complicated your data is :

$output = "{desc:'User defined payload',asc:'whatever'}";

function json_js_php($string){

    $string = str_replace("{",'{"',$string);
    $string = str_replace(":'",'":"',$string);
    $string = str_replace("',",'","',$string);
    $string = str_replace("'}",'"}',$string);
    return $string;

}

echo json_decode(json_js_php($output))->{'desc'}; 

returns : User defined payload


Using regexp is a no-go. JSON grammar cannot be correctly parsed using regexp. You will open yourself to a ton of future bugs.

I recommend using some kind of a YAML parser. YAML is backwards-compatible with JSON and allows unquoted literals at the same time.

Symfony YAML component worked great for me.

And remember that there will be a performance penalty in comparison to json_decode because it's implemented natively.


If the problem is just the unquoted identifiers and the data can be assumed not to contain any curly brackets, this should do it:

$goodJson = preg_replace("/{\s*([a-zA-Z0-9_]+)/", '{ "$1"', $badJson);

(not tested!)


Try this:

$jsonString = "{result:true,username:'usr000242',password:'123456',message:'Cannot send username and password to email@test.com'}";
function manualFixInvalidJSON($jsonString=''){
    $jsonString = preg_replace("/([{,])([a-zA-Z][^: ]+):/", "\$1\"$2\":", $jsonString);
    $jsonString = preg_replace("/:([a-zA-Z\'][^:]+)([,}])/", ":\"$1\"$2", $jsonString);
    $jsonString = json_decode($jsonString,true);
    function trimer($val){
        return trim(trim($val,"'"),"\"");
    }
    $jsonString = array_map('trimer', $jsonString);
    return json_encode($jsonString);
}
echo jsonString($jsonString);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜