note 113938 added to function.json-decode

From: Date: Wed, 18 Dec 2013 21:37:52 +0000
Subject: note 113938 added to function.json-decode
Groups: php.notes 
Request: Send a blank email to php-notes+get-197980@lists.php.net to get a copy of this message
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 ) ) ---- Server IP: 72.52.91.14 Probable Submitter: 72.52.91.14 ---- Manual Page -- http://php.net/manual/en/function.json-decode.php Edit -- https://master.php.net/note/edit/113938 Del: integrated -- https://master.php.net/note/delete/113938/integrated Del: useless -- https://master.php.net/note/delete/113938/useless Del: bad code -- https://master.php.net/note/delete/113938/bad+code Del: spam -- https://master.php.net/note/delete/113938/spam Del: non-english -- https://master.php.net/note/delete/113938/non-english Del: in docs -- https://master.php.net/note/delete/113938/in+docs Del: other reasons-- https://master.php.net/note/delete/113938 Reject -- https://master.php.net/note/reject/113938 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#197980) next »