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:
<?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->valid()) {
$i = $generator->current();
switch ($i) {
case ' ':
case "\n":
continue;
case '{':
$generator->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->next();
}
return $data;
}
/**
* @param string $str
* @return \Generator
*/
private static function stringIterator($str)
{
for ($i = 0; $i < strlen($str); $i++) {
yield $str[$i];
}
}
}
And here's the usage:
>>> $result = \Foo\Bar\NotJsonParser::parseNotJSON("{foo:{qux:1,quux:0}, bar:{}}");
=> [
"foo" => [
"qux" => "1",
"quux" => "0",
],
"bar" => [],
]
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.