How to keep json_encode() from dropping strings with invalid characters

后端 未结 6 710
醉话见心
醉话见心 2020-11-29 06:24

Is there a way to keep json_encode() from returning null for a string that contains an invalid (non-UTF-8) character?

It can be a pain in t

6条回答
  •  囚心锁ツ
    2020-11-29 06:50

    to get a informational error notification on json failures we use this helper:

    • installs temporarily a custom error handler to catch json errors for encoding/decoding
    • throws RuntimeException on error
    'foo']);
     * $array = HelperJson::decode('{"bla":"foo"}');
     * 
     * throws exception on failure
     * 
     */
    class HelperJson {
    
        /**
         * @var array
         */
        static private $jsonErrors = [
                JSON_ERROR_NONE => '',
                JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
                JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
                JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch',
                JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
                JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
        ];
    
        /**
         * ! assoc ! (reverse logic to php function)
         * @param string $jsonString
         * @param bool $assoc
         * @throws RuntimeException
         * @return array|null
         */
        static public function decode($jsonString, $assoc=true){
    
            HelperJson_ErrorHandler::reset(); // siehe unten
            set_error_handler('HelperJson_ErrorHandler::handleError');
    
            $result = json_decode($jsonString, $assoc);
    
            $errStr = HelperJson_ErrorHandler::getErrstr();
            restore_error_handler();
    
            $jsonError = json_last_error();
            if( $jsonError!=JSON_ERROR_NONE ) {
                $errorMsg = isset(self::$jsonErrors[$jsonError]) ? self::$jsonErrors[$jsonError] : 'unknown error code: '.$jsonError;
                throw new \RuntimeException('json decoding error: '.$errorMsg.' JSON: '.substr($jsonString,0, 250));
            }
            if( $errStr!='' ){
                throw new \RuntimeException('json decoding problem: '.$errStr.' JSON: '.substr($jsonString,0, 250));
            }
            return $result;
        }
    
        /**
         * encode with error "throwing"
         * @param mixed $data
         * @param int $options   $options=JSON_PRESERVE_ZERO_FRACTION+JSON_UNESCAPED_SLASHES : 1024 + 64 = 1088
         * @return string
         * @throws \RuntimeException
         */
        static public function encode($data, $options=1088){
    
            HelperJson_ErrorHandler::reset();// scheint notwendg da sonst bei utf-8 problemen nur eine warnung geflogen ist, die hier aber nicht durchschlug, verdacht der error handler macht selbst was mit json und reset damit json_last_error
            set_error_handler('HelperJson_ErrorHandler::handleError');
    
            $result = json_encode($data, $options);
    
            $errStr = HelperJson_ErrorHandler::getErrstr();
            restore_error_handler();
    
            $jsonError = json_last_error();
            if( $jsonError!=JSON_ERROR_NONE ){
                $errorMsg = isset(self::$jsonErrors[$jsonError]) ? self::$jsonErrors[$jsonError] : 'unknown error code: '.$jsonError;
                throw new \RuntimeException('json encoding error: '.$errorMsg);
            }
            if( $errStr!='' ){
                throw new \RuntimeException('json encoding problem: '.$errStr);
            }
            return $result;
        }
    
    }
    
    /**
    
    HelperJson_ErrorHandler::install();
    preg_match('~a','');
    $errStr = HelperJson_ErrorHandler::getErrstr();
    HelperJson_ErrorHandler::remove();
    
     *
     */
    class HelperJson_ErrorHandler {
    
        static protected  $errno = 0;
        static protected  $errstr = '';
        static protected  $errfile = '';
        static protected  $errline = '';
        static protected  $errcontext = array();
    
        /**
         * @param int $errno
         * @param string $errstr
         * @param string $errfile
         * @param int $errline
         * @param array $errcontext
         * @return bool
         */
        static public function handleError($errno, $errstr, $errfile, $errline, $errcontext){
            self::$errno = $errno;
            self::$errstr = $errstr;
            self::$errfile = $errfile;
            self::$errline = $errline;
            self::$errcontext = $errcontext;
            return true;
        }
    
        /**
         * @return int
         */
        static public function getErrno(){
            return self::$errno;
        }
        /**
         * @return int
         */
        static public function getErrstr(){
            return self::$errstr;
        }
        /**
         * @return int
         */
        static public function getErrfile(){
            return self::$errfile;
        }
        /**
         * @return int
         */
        static public function getErrline(){
            return self::$errline;
        }
        /**
         * @return array
         */
        static public function getErrcontext(){
            return self::$errcontext;
        }
        /**
         * reset last error
         */
        static public function reset(){
            self::$errno = 0;
            self::$errstr = '';
            self::$errfile = '';
            self::$errline = 0;
            self::$errcontext = array();
        }
    
        /**
         * set black-hole error handler
         */
        static public function install(){
            self::reset();
            set_error_handler('HelperJson_ErrorHandler::handleError');
        }
    
        /**
         * restore previous error handler
         */
        static function remove(){
            restore_error_handler();
        }
    }
    
    

提交回复
热议问题