php json decode implement

For users of php 5.1.6 or lower.

FastJSON.class.php

 <?php/**_______________________________________ * *  FastJSON (strict version for PHP 5.2 or greater), *  simple and fast Pear Service_JSON encoder/decoder alternative *  [http://pear.php.net/pepr/pepr-proposal-show.php?id=198] * --------------------------------------- * This class is about two time faster than Pear Service_JSON class. * This class is probably not powerful as Service_JSON but it has * no dependencies and converts correctly ASCII range 0x00 - 0x1F too. * There's any string convertion, just regular RFC specific characters are converted * into \u00XX string. * To don't have problems with other chars try to use utf8_encode($json_encoded_string). * To recieve correctly JSON strings from JavaScript use encodeURIComponent then * use, if is necessary, utef8_decode before JS to PHP convertion. * decode method doesn't returns a standard object class but You can * create the corret class directly with FastJSON::convert method * and with them You can manage JS Date objects too. * --------------------------------------- * Summary of static public methods * *  convert *          extra, special method * *  decode *          converts a valid JSON string *          into a native PHP variable * *  encode *          converts a native php variable *          into a valid JSON string * --------------------------------------- * * Special FastJSON::convert method Informations * _______________________________________ * --------------------------------------- * This method is used by FastJSON::encode method but should be used * to do these convertions too: * * - JSON string to time() integer: * *      FastJSON::convert(decodedDate:String):time() * *  If You recieve a date string rappresentation You *  could convert into respective time() integer. *  Example: *      FastJSON::convert(FastJSON::decode($clienttime)); *      // i.e. $clienttime = 2006-11-09T14:42:30 *      // returned time will be an integer useful with gmdate or date *      // to create, for example, this string *          // Thu Nov 09 2006 14:42:30 GMT+0100 (Rome, Europe) * * - time() to JSON string: * *      FastJSON::convert(time():Int32, true:Boolean):JSON Date String format * *  You could send server time() informations and send them to clients. *  Example: *      FastJSON::convert(time(), true); *      // i.e. 2006-11-09T14:42:30 * * - associative array to generic class: * *      FastJSON::convert(array(params=>values), new GenericClass):new Instance of GenericClass * *  With a decoded JSON object You could convert them *  into a new instance of your Generic Class. *  Example: *      class MyClass { *          var $param = "somevalue"; *          function MyClass($somevar) { *              $this->somevar = $somevar; *          }; *          function getVar = function(){ *              return $this->somevar; *          }; *      }; * *      $instance = new MyClass("example"); *      $encoded = FastJSON::encode($instance); *      // {"param":"somevalue"} * *      $decoded = FastJSON::decode($encoded); *      // $decoded instanceof Object   => true *      // $decoded instanceof MyClass  => false * *      $decoded = FastJSON::convert($decoded, new MyClass("example")); *      // $decoded instanceof Object   => true *      // $decoded instanceof MyClass  => true * *      $decoded->getVar(); // example * * --------------------------------------- * * @author      Andrea Giammarchi * @site        http://www.devpro.it/ * @version     0.4 [fixed string convertion problems, add stdClass optional convertion instead of associative array (used by default)] * @requires    anything * @compatibility   PHP >= 5 * @license * --------------------------------------- * * Copyright (c) 2006 - 2007 Andrea Giammarchi * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated * documentation files (the "Software"), * to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * _______________________________________ */class FastJSON {    // public methods    /**     * public static method     *     *  FastJSON::convert(params:* [, result:Instance]):*     *     * @param   *   String or Object     * @param   Instance    optional new generic class instance if first     *              parameter is an object.     * @return  *   time() value or new Instance with object parameters.     *     * @note    please read Special FastJSON::convert method Informations     */    static public function convert($params, $result = null){        switch(gettype($params)){            case    'array':                    $tmp = array();                    foreach($params as $key => $value) {                        if(($value = FastJSON::encode($value)) !== '')                            array_push($tmp, FastJSON::encode(strval($key)).':'.$value);                    };                    $result = '{'.implode(',', $tmp).'}';                    break;            case    'boolean':                    $result = $params ? 'true' : 'false';                    break;            case    'double':            case    'float':            case    'integer':                    $result = $result !== null ? strftime('%Y-%m-%dT%H:%M:%S', $params) : strval($params);                    break;            case    'NULL':                    $result = 'null';                    break;            case    'string':                    $i = create_function('&$e, $p, $l', 'return intval(substr($e, $p, $l));');                    if(preg_match('/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $params))                        $result = mktime($i($params, 11, 2), $i($params, 14, 2), $i($params, 17, 2), $i($params, 5, 2), $i($params, 9, 2), $i($params, 0, 4));                    break;            case    'object':                    $tmp = array();                    if(is_object($result)) {                        foreach($params as $key => $value)                            $result->$key = $value;                    } else {                        $result = get_object_vars($params);                        foreach($result as $key => $value) {                            if(($value = FastJSON::encode($value)) !== '')                                array_push($tmp, FastJSON::encode($key).':'.$value);                        };                        $result = '{'.implode(',', $tmp).'}';                    }                    break;        }        return $result;    }    /**     * public method     *     *  FastJSON::decode(params:String[, useStdClass:Boolean]):*     *     * @param   String  valid JSON encoded string     * @param   Bolean  uses stdClass instead of associative array if params contains objects (default false)     * @return  *   converted variable or null     *              is params is not a JSON compatible string.     * @note    This method works in an optimist way. If JSON string is not valid     *      the code execution will die using exit.     *      This is probably not so good but JSON is often used combined with     *      XMLHttpRequest then I suppose that's better more protection than     *      just some WARNING.     *      With every kind of valid JSON string the old error_reporting level     *      and the old error_handler will be restored.     *     * @example     *      FastJSON::decode('{"param":"value"}'); // associative array     *      FastJSON::decode('{"param":"value"}', true); // stdClass     *      FastJSON::decode('["one",two,true,false,null,{},[1,2]]'); // array     */    static public function decode($encode, $stdClass = false){        $pos = 0;        $slen = is_string($encode) ? strlen($encode) : null;        if($slen !== null) {            $error = error_reporting(0);            set_error_handler(array('FastJSON', '__exit'));            $result = FastJSON::__decode($encode, $pos, $slen, $stdClass);            error_reporting($error);            restore_error_handler();        }        else            $result = null;        return $result;    }    /**     * public method     *     *  FastJSON::encode(params:*):String     *     * @param   *       Array, Boolean, Float, Int, Object, String or NULL variable.     * @return  String      JSON genric object rappresentation     *              or empty string if param is not compatible.     *     * @example     *      FastJSON::encode(array(1,"two")); // '[1,"two"]'     *     *      $obj = new MyClass();     *      obj->param = "value";     *      obj->param2 = "value2";     *      FastJSON::encode(obj); // '{"param":"value","param2":"value2"}'     */    static public function encode($decode){        $result = '';        switch(gettype($decode)){            case    'array':                    if(!count($decode) || array_keys($decode) === range(0, count($decode) - 1)) {                        $keys = array();                        foreach($decode as $value) {                            if(($value = FastJSON::encode($value)) !== '')                                array_push($keys, $value);                        }                        $result = '['.implode(',', $keys).']';                    }                    else                        $result = FastJSON::convert($decode);                    break;            case    'string':                    $replacement = FastJSON::__getStaticReplacement();                    $result = '"'.str_replace($replacement['find'], $replacement['replace'], $decode).'"';                    break;            default:                    if(!is_callable($decode))                        $result = FastJSON::convert($decode);                    break;        }        return $result;    }    // private methods, uncommented, sorry    static private function __getStaticReplacement(){        static $replacement = array('find'=>array(), 'replace'=>array());        if($replacement['find'] == array()) {            foreach(array_merge(range(0, 7), array(11), range(14, 31)) as $v) {                $replacement['find'][] = chr($v);                $replacement['replace'][] = "\\u00".sprintf("%02x", $v);            }            $replacement['find'] = array_merge(array(chr(0x5c), chr(0x2F), chr(0x22), chr(0x0d), chr(0x0c), chr(0x0a), chr(0x09), chr(0x08)), $replacement['find']);            $replacement['replace'] = array_merge(array('\\\\', '\\/', '\\"', '\r', '\f', '\n', '\t', '\b'), $replacement['replace']);        }        return $replacement;    }    static private function __decode(&$encode, &$pos, &$slen, &$stdClass){        switch($encode{$pos}) {            case 't':                $result = true;                $pos += 4;                break;            case 'f':                $result = false;                $pos += 5;                break;            case 'n':                $result = null;                $pos += 4;                break;            case '[':                $result = array();                ++$pos;                while($encode{$pos} !== ']') {                    array_push($result, FastJSON::__decode($encode, $pos, $slen, $stdClass));                    if($encode{$pos} === ',')                        ++$pos;                }                ++$pos;                break;            case '{':                $result = $stdClass ? new stdClass : array();                ++$pos;                while($encode{$pos} !== '}') {                    $tmp = FastJSON::__decodeString($encode, $pos);                    ++$pos;                    if($stdClass)                        $result->$tmp = FastJSON::__decode($encode, $pos, $slen, $stdClass);                    else                        $result[$tmp] = FastJSON::__decode($encode, $pos, $slen, $stdClass);                    if($encode{$pos} === ',')                        ++$pos;                }                ++$pos;                break;            case '"':                switch($encode{++$pos}) {                    case '"':                        $result = "";                        break;                    default:                        $result = FastJSON::__decodeString($encode, $pos);                        break;                }                ++$pos;                break;            default:                $tmp = '';                preg_replace('/^(\-)?([0-9]+)(\.[0-9]+)?([eE]\+[0-9]+)?/e', '$tmp = "\\1\\2\\3\\4"', substr($encode, $pos));                if($tmp !== '') {                    $pos += strlen($tmp);                    $nint = intval($tmp);                    $nfloat = floatval($tmp);                    $result = $nfloat == $nint ? $nint : $nfloat;                }                break;        }        return $result;    }    static private function __decodeString(&$encode, &$pos) {        $replacement = FastJSON::__getStaticReplacement();        $endString = FastJSON::__endString($encode, $pos, $pos);        $result = str_replace($replacement['replace'], $replacement['find'], substr($encode, $pos, $endString));        $pos += $endString;        return $result;    }    static private function __endString(&$encode, $position, &$pos) {        do {            $position = strpos($encode, '"', $position + 1);        }while($position !== false && FastJSON::__slashedChar($encode, $position - 1));        if($position === false)            trigger_error('', E_USER_WARNING);        return $position - $pos;    }    static private function __exit($str, $a, $b) {        exit($a.'FATAL: FastJSON decode method failure [malicious or incorrect JSON string]');    }    static private function __slashedChar(&$encode, $position) {        $pos = 0;        while($encode{$position--} === '\\')            $pos++;        return $pos % 2;    }}?>

References

  1. json_decode
  2. Services_JSON
  3. Zend_JSON
  4. FastJSON