Parser for json-like format in PHP At work they use a format similar to JSON but without quotes that looks like this:

{foo:{qux:1,quux:0}, bar:{}}


The reason they don't just use json is because the C# package Newtonsoft.Json can deserialize this like if it was regular json and it works. I need to use it in Php but json_decode is not as forgiving.

So here's my attempt at a simple parser:

&lt;?php

namespace Foo\Bar;


class NotJsonParser
{
    const STEP_NAME = 0;
    const STEP_VALUE = 1;

    /**
     * @param $string
     * @return array
     */
    public static function parseNotJSON($string)
    {
        $generator = self::stringIterator($string);
        $data = self::parser($generator);
        return $data[''];
    }

    /**
     * @param \Generator $generator
     * @return array
     */
    private static function parser(\Generator $generator)
    {
        $data = [];
        $step = self::STEP_NAME;
        $name = '';
        $value = '';

        while ($generator-&gt;valid()) {
            $i = $generator-&gt;current();
            switch ($i) {
                case ' ':
                case "\n":
                    continue;
                case '{':
                    $generator-&gt;next();
                    $value = self::parser($generator);
                    $data[$name] = $value;
                    $step = self::STEP_NAME;
                    $name = '';
                    $value = '';
                    break;
                case '}':
                    if ($name) {
                        $data[$name] = $value;
                    }
                    return $data;
                case ',':
                    if ($name) {
                        $data[$name] = $value;
                    }
                    $step = self::STEP_NAME;
                    $name = '';
                    $value = '';
                    break;
                case ':':
                    $step = self::STEP_VALUE;
                    break;
                default:
                    if ($step === self::STEP_NAME) {
                        $name .= $i;
                    } else {
                        $value .= $i;
                    }
            }
            $generator-&gt;next();
        }
        return $data;
    }

    /**
     * @param string $str
     * @return \Generator
     */
    private static function stringIterator($str)
    {
        for ($i = 0; $i &lt; strlen($str); $i++) {
            yield $str[$i];
        }
    }
}


And here's the usage:

&gt;&gt;&gt; $result = \Foo\Bar\NotJsonParser::parseNotJSON("{foo:{qux:1,quux:0}, bar:{}}");
=&gt; [
     "foo" =&gt; [
       "qux" =&gt; "1",
       "quux" =&gt; "0",
     ],
     "bar" =&gt; [],
   ]


How could I improve this? I know it really lacks error handling. I don't mind that the numbers stay as strings. Also the format never goes more than 2 levels deep. Whitespace between tokens is non important but there shouldn't be whitespace inside the keys (e.g.: {foo bar: baz} should be an error).

Also how should I encode it back from an array to a string? I was thinking just using json_encode and then removing the quote characters.
The following workaround will wrap your keys and values with double quotes.  Such hacks will always be vulnerable to edge cases.  To avoid sprinting down a rabbit hole of possibilities (I can think of a few cases off the top of my head -- 1. keys/values already containing quotes 2. declared empty/null keys ...there will be more), I'll just provide a solution for your sample input.

For now, I'm using \w to ensure that the space before bar is not included.  There are several ways to do this action, but I would need to have intimate knowledge of your project data to develop the expression that I feel is "best / most robust".

If you discover any fringe cases that break this simple regex pattern, please update your question and I can create a patch.

Code: (Demo)

$unquoted_json = &lt;&lt;&lt;NOTJSON
{foo:{qux:1,quux:0}, bar:{}}
NOTJSON;

$quoted_json = preg_replace('~\w[^:{},]*~', '"$0"', $unquoted_json);
$array = json_decode($quoted_json, true);
var_export($array);
echo "\n---\n";
echo json_encode($array);


Output:

array (
  'foo' =&gt; 
  array (
    'qux' =&gt; '1',
    'quux' =&gt; '0',
  ),
  'bar' =&gt; 
  array (
  ),
)
---
{"foo":{"qux":"1","quux":"0"},"bar":[]}