18

I have json data represented like this

{key:"value"}

(no quotes 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...

4
  • There is not built in function but like said adam looks from where you are getting your JSON to send it properly Commented Aug 4, 2011 at 12:53
  • 3
    It's not uncommon for JSON to come across this way, unfortunately. Google does it... google.com/ig/calculator?hl=en&q=1%20USD=?CAD Commented May 22, 2013 at 10:39
  • Your link returns a 404 @Laizer and the JSON listed here is not valid. Commented Apr 23, 2015 at 21:03
  • See this answer for a good solution: stackoverflow.com/a/61386431/250775 Commented Nov 10, 2023 at 12:07

9 Answers 9

15

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));
}
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for this solution. But I had to remove sprintf('{%s}', $s) and had to use just $s as the argument for json_decode function.
Excellent Solution. I am not sure why Manjula didnt ACCEPT this as the correct answer yet... over 2 years later...
Not a valid solution! Try setting a key or "value" to a url or something with a colon in it. This will fail. eg {key:"va:lue"}
preg_replace('/(\n[\s||\t]*)(\w+):[\s||\t]/i', '$1"$2":', $json);
simply does not add any quote to my json..why is this even voted so much
|
11

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"
}

1 Comment

thanks, exactly what i was looking for, and still works in modern versions of PHP after all these years (tested on 7.3) - btw if you want arrays instead of objects then construct it as $json_decoder = new Services_JSON(SERVICES_JSON_IN_ARR | SERVICES_JSON_LOOSE_TYPE);
8

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);

Comments

4

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)  );

2 Comments

how to add this to laravel controller?
This worked perfectly and decoded the broken JSON into the correct array. I was then able to call json_encode to correctly encode it. Thank you!
3

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.

Comments

3
$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

1 Comment

Thanks, this is what I've been looking for. And to make it work, you have to make sure that there is a space after the colon. E.g. "{a:d, b:'c'}" -> this won't work. "{a: d, b: 'c'}" -> this will work.
0

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?

2 Comments

.. thus you have no "json data" - at least no valid ones.
This would have been more appropriate as a comment, as it does not attempt to answer the question "How can I add the quotes..."
0

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);

3 Comments

This will add double quotes inside values, while it will miss the keys if they have no white space around them: {s:"this is my string", flag: false , n: 9 } will become {s:"this"is"my string", flag:"false", n:"9"}.
just add the : in the regex, it should be actually voted as a good answer
The i modifier is pointless -- \w is already case-insensitive.
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.