开发者

php json_decode fails without quotes on key

开发者 https://www.devze.com 2023-03-25 16:45 出处:网络
I have json data represented like this {key:\"value\"} (no quo开发者_StackOverflow社区tes arround key...)

I have json data represented like this

{key:"value"}

(no quo开发者_StackOverflow社区tes arround key...)

I want to translate it to an associative array.

PHP's json_decode returns null

How can I add the quotes around the key?? thanks...


You can either fix the JSON at the source so that it returns a valid JSON structure, or you can manually add quotes around the keys.

This answer to a similar question has an example of how to do that:

function my_json_decode($s) {
    $s = str_replace(
        array('"',  "'"),
        array('\"', '"'),
        $s
    );
    $s = preg_replace('/(\w+):/i', '"\1":', $s);
    return json_decode(sprintf('{%s}', $s));
}


If you can't turn that into valid JSON at the source, then you can use Services_JSON from PEAR to parse it, since adding quotes around the key is a non-trivial error-prone process.

Services_JSON will correctly parse the invalid key string.

Example:

$json = new Services_JSON();
var_dump($json->decode('{key:"value"}'));

Output:

object(stdClass)#2 (1) {
  ["key"]=>
  string(5) "value"
}


To avoid that double quotes are inserted in places where they shouldn't, you should skip those quoted strings in this manipulation.

For instance, if you have this JavaScript object literal in a string:

{
   dt:"2016-10-22T09:13:20",
   "x:y":false
}

... then care must be taken not to have 22T09: change into "22T09":. Also the already quoted key, "x:y" should stay unaltered.

You could use this regular expression for achieving that:

preg_replace('/("(.*?)"|(\w+))(\s*:\s*(".*?"|.))/s', '"$2$3"$4', $text);

Other issues

JavaScript object literals allow numeric constants with left-padded zeroes, like 001, and/or with the unary + sign, which are neither allowed in JSON. To remove those offending characters also, you could use this extended version:

preg_replace('/("(.*?)"|(\w+))(\s*:\s*)\+?(0+(?=\d))?(".*?"|.)/s', '"$2$3"$4$6', $text);


Please do not use regexps to do this! JSON grammar cannot be correctly parsed this way by definition. You will open yourself to a ton of future bugs.

I recommend using a YAML parser, because YAML is a superset of JSON and allows unquoted literals at the same time.

Symfony YAML component works great.

There will be a performance penalty in comparison to json_decode which is implemented natively.


DON'T USE REGEX.

REGEX is totally not recommended for such cases, don't use that for parsing such data. If you have a simple goals and want to avoid the stable PEAR package, then you might try JSON-php library (but no-longer maintained).

1) Get JSON.phps file from here and rename to .php and replace constructor function names to __construct.

2) usage:

$content = '{myKey:"valueeeee"}';

include(__DIR__.'/JSON.php'); 
$this->json = new Services_JSON( SERVICES_JSON_LOOSE_TYPE );  // to return objects instead of Associative array, remove the argument
var_dump( $this->json->decode($content)  );


$results = \Symfony\Component\Yaml\Yaml::parse("{a: d, b: 'c', e: [a, 3]}");

You probably can only use that lib without having to use the whole Symfony package : https://packagist.org/packages/symfony/yaml


As per the documentation (see Example #3 - 'common mistakes using json_decode'), keys must be enclosed in double quotes.

Where are you getting the JSON data?


This worked for me, using regex replace '/\s(\w+)\s/i'

$json =  file_get_contents("php://input"); // or whatever json data
$json = preg_replace('/\s(\w+)\s/i', '"$1"', $json);
$json = json_decode($json, true);


I tested many of the solutions proposed here and nothing worked correctly.

  • @Intelekshual does not work with more "complex" cases.
$json='{hello:{a:2,b:3},world:[1,2,3,"aaa","bbbb"]}';

var_dump(my_json_decode($json)); // returns null

function my_json_decode($s) {
    $s = str_replace(
        array('"',  "'"),
        array('\"', '"'),
        $s
    );
    $s = preg_replace('/(\w+):/i', '"\1":', $s);
    return json_decode(sprintf('{%s}', $s));
}
  • @rid and @T.Todua the library does not work because the code targets PHP 4.x/5.x and it has many deprecated features.

So I created an adaptation of Services_JSON (PECL) and updated the code to PHP 7.2 and higher (including PHP 8.1). It works with Composer and it doesn't have any other dependency.

https://github.com/EFTEC/Services_JSON

Or you could copy and paste the code from here:

https://github.com/EFTEC/Services_JSON/blob/main/src/Services_JSON.php

0

精彩评论

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