note 113938 deleted from function.json-decode by salathe

From: Date: Mon, 21 Sep 2020 15:00:37 +0000
Subject: note 113938 deleted from function.json-decode by salathe
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-215422@lists.php.net to get a copy of this message
Note Submitter: kuroi dot neko at wanadoo dot fr ---- My initial problem was to have PHP check a form in case JavaScript was disabled on the client. I fiddled with json_decode for a while before realizing what I really wanted: to be able to initialize the same object in PHP and JavaScript from a common source file. I ended up writing a tiny parser for a JavaScript object initializer, which is close to - but not the same thing as - a piece of JSON. Among other things, it - recognizes regexes (turning them into PHP strings), - handles C/C++ comments - accepts non-quoted field names. This parser will accept a superset of real JS object initializer syntax (for instance non-quoted string litterals or improperly formed regexes). Error report and sanity checks are close to non-existent. The whole idea is to share the code among JavaScript and PHP, so the syntactical checks are left to the JS interpreter. Here is the code for those who are interrested : ----------------------------- class JSvarDecoderCtx { public function __construct ($type) { $this->fields = ($type == '[') ? array() : new stdClass(); } public function add_name (&$text) { $this->name = $text; $text = ''; } public function add_value (&$text) { // weird input like a mix of fields and array elements will cause warnings here if (!isset ($this->name)) $this->fields[ ] = $text; else $this->fields->{$this->name} = $text; $text = ''; } } define ('JSVAL_TEXT' , 12001); define ('JSVAL_STRING', 12002); define ('JSVAL_REGEXP', 12003); define ('JSVAL_COMMT1', 12004); define ('JSVAL_COMMT2', 12005); function jsinit_decode ($json) { // parse a JS initializer $stack = array (); $text = ""; $state = JSVAL_TEXT; $len = strlen($json); for ($i = 0 ; $i != $len; $i++) { $c = $json[$i]; switch ($state) { case JSVAL_TEXT: switch ($c) { case '{' : case '[' : array_unshift ($stack, new JSvarDecoderCtx ($c)); break; case '}' : case ']' : $stack[0]->add_value ($text); $text = array_shift ($stack)->fields; break; case ':' : $stack[0]->add_name ($text); break; case ',' : $stack[0]->add_value ($text); break; case '"' : case "'" : $closer = $c; $state = JSVAL_STRING; break; case '/' : assert($i != ($len-1)); switch ($json[$i+1]) { case '/': $state = JSVAL_COMMT1; break; case '*': $state = JSVAL_COMMT2; break; default : $state = JSVAL_REGEXP; $text .= $c; } break; case "\r": case "\n": case "\t": case ' ' : break; default : $text .= $c; } break; case JSVAL_STRING: if ($c != $closer) $text .= $c; else $state = JSVAL_TEXT; break; case JSVAL_REGEXP: if (($c != ',') && ($c != '}')) $text .= $c; else { $i--; $state = JSVAL_TEXT; } break; case JSVAL_COMMT1: if (($c == "\r") || ($c == "\n")) $state = JSVAL_TEXT; break; case JSVAL_COMMT2: if ($c != '*') break; assert($i != ($len-1)); if ($json[$i+1] == '/') { $i++; $state = JSVAL_TEXT; } } } assert ($state == JSVAL_TEXT); return $text; } ----------------------------- Test pattern : { errors: "form-errors", // CSS class for validation errors tooltip i: /* integer */ /^[0-9]+$/, err: { '*': "mandatory field", i: "must be an integer", }, a:['ga','bu','zo','meuh'] // http://www.archimedes-lab.org/shadoks/shadoiku.html } ----------------------------- result : stdClass Object ( [errors] => form-errors [i] => /^[0-9]+$/ [err] => stdClass Object ( [*] => mandatory field [i] => must be an integer ) [a] => Array ( [0] => ga [1] => bu [2] => zo [3] => meuh ) )

« previous php.notes (#215422) next »