如何解决此解码和语法错误

Posted

技术标签:

【中文标题】如何解决此解码和语法错误【英文标题】:How can I solve this decode and syntax error 【发布时间】:2020-12-26 05:56:56 【问题描述】:

我的 php 脚本有问题。 (我和我的朋友写这篇文章对错误感到抱歉) 这是向我展示的错误:

致命错误:未捕获的 InvalidArgumentException:json_decode 错误: 语法错误 /opt/html/wordpress_eagle/forums/vendor/guzzlehttp/guzzle/src/functions.php:306 堆栈跟踪:#0 /opt/html/wordpress_eagle/forums/vendor/restcord/restcord/src/DiscordClient.php(229): GuzzleHttp\json_decode('')#1 /opt/html/wordpress_eagle/forums/vendor/restcord/restcord/src/DiscordClient.php(184): RestCord\DiscordClient->convertResponseToResult('guild', Array, 对象(GuzzleHttp\Psr7\Response),对象(GuzzleHttp\Command\Command)) #2 /opt/html/wordpress_eagle/forums/vendor/guzzlehttp/command/src/ServiceClient.php(215): RestCord\DiscordClient->RestCordclosure(对象(GuzzleHttp\Psr7\Response), 对象(GuzzleHttp\Psr7\Request),对象(GuzzleHttp\Command\Command)) #3 /opt/html/wordpress_eagle/forums/vendor/guzzlehttp/command/src/ServiceClient.php(177): GuzzleHttp\Command\ServiceClient->transformResponseToResult(对象(GuzzleHttp\Psr7\Response), 对象(GuzzleHttp\Psr7\Request),对象(GuzzleHttp\Command\Command)) #4 [内部函数]:/opt/html/wordpress_eagle/forums/vendor/guzzlehttp/command/src/Exception/CommandException.php 中的 GuzzleHtt 第 57 行

这是 json_decode 抛出错误 GuzzleHttp/src/functions.php 的地方: https://github.com/guzzle/guzzle/blob/4.1.0/src/functions.php#L305

 *
 * @param string $json    JSON data to parse
 * @param bool $assoc     When true, returned objects will be converted
 *                        into associative arrays.
 * @param int    $depth   User specified recursion depth.
 * @param int    $options Bitmask of JSON decode options.
 *
 * @return mixed
 * @throws \InvalidArgumentException if the JSON cannot be decoded.
 * @link http://www.php.net/manual/en/function.json-decode.php
 */ 
function json_decode( $json, $assoc = false, $depth = 512, $options = 0) ### 306 line in function.php

    
    $data = \json_decode($json, $assoc, $depth, $options);
    if (JSON_ERROR_NONE !== json_last_error()) 
        throw new \InvalidArgumentException(
            'json_decode error: ' . json_last_error_msg()
        );
    
    
    return $data;


/**
 * Wrapper for JSON encoding that throws when an error occurs.
 *
 * @param mixed $value   The value being encoded
 * @param int    $options JSON encode option bitmask
 * @param int    $depth   Set the maximum depth. Must be greater than zero.
 *
 * @return string
 * @throws \InvalidArgumentException if the JSON cannot be encoded.
 * @link http://www.php.net/manual/en/function.json-encode.php
 */
function json_encode($value, $options = 0, $depth = 512)

    $json = \json_encode($value, $options, $depth);
    if (JSON_ERROR_NONE !== json_last_error()) 
        throw new \InvalidArgumentException(
            'json_encode error: ' . json_last_error_msg()
        );
    

    return $json;

这是来自 commandexception.php 的行:

       // Create the exception.
        return new $class($message, $command, $prev, $request, $response); ### this is underlined like Fatal Error.
    

discordclient.php: ### restcord https://github.com/restcord/restcord/blob/master/src/DiscordClient.php

class DiscordClient

    /**
     * @var array
     */
    private $options;

    /**
     * @var GuzzleClient[]
     */
    private $categories = [];

    /**
     * @var Logger
     */
    private $logger;

    /**
     * Client constructor.
     *
     * @param array $options
     */
    public function __construct(array $options = [])
    
        $this->options = $this->validateOptions($options);
        $this->logger  = $this->options['logger'];

        $stack = HandlerStack::create();
        $stack->push(
            new RateLimiter(
                $this->options['rateLimitProvider'],
                $this->options,
                $this->logger
            )
        );

        $stack->push(
            Middleware::log(
                $this->logger,
                new MessageFormatter('response', $this->options['token'])
            )
        );
        $stack->push(
            Middleware::log(
                $this->logger,
                new MessageFormatter('url request', $this->options['token'])
            )
        );

        $defaultGuzzleOptions           = [
            'base_uri'    => $this->options['apiUrl'],
            'headers'     => [
                'Authorization' => $this->getAuthorizationHeader($this->options['tokenType'], $this->options['token']),
                'User-Agent'    => "DiscordBot (https://github.com/aequasi/php-restcord, $this->getVersion())",
                'Content-Type'  => 'application/json',
            ],
            'http_errors' => isset($this->options['httpErrors']) ? $this->options['httpErrors'] : true,
            'handler'     => $stack,
        ];
        $this->options['guzzleOptions'] = array_merge($this->options['guzzleOptions'], $defaultGuzzleOptions);

        $client = new Client($this->options['guzzleOptions']);

        $this->buildDescriptions($client);
    

    /**
     * @param string $name
     *
     * @throws \Exception
     *
     * @return GuzzleClient
     */
    public function __get($name)
    
        if (!isset($this->categories[$name])) 
            throw new \Exception('No category with the name: '.$name);
        

        return $this->categories[$name];
    

    /**
     * @param array $options
     *
     * @return array
     */
    private function validateOptions(array $options)
    
        $currentVersion = 6;
        $resolver       = new OptionsResolver();
        $resolver->setDefaults(
            [
                'version'           => $currentVersion,
                'logger'            => new Logger('Logger'),
                'rateLimitProvider' => new MemoryRateLimitProvider(),
                'throwOnRatelimit'  => false,
                'apiUrl'            => "https://discord.com/api/v$currentVersion/",
                'tokenType'         => 'Bot',
                'cacheDir'          => __DIR__.'/../../../cache/',
                'guzzleOptions'     => [],
            ]
        )
            ->setDefined(['token'])
            ->setAllowedValues('tokenType', ['Bot', 'OAuth'])
            ->setAllowedTypes('token', ['string'])
            ->setAllowedTypes('apiUrl', ['string'])
            ->setAllowedTypes('rateLimitProvider', [AbstractRateLimitProvider::class])
            ->setAllowedTypes('throwOnRatelimit', ['bool'])
            ->setAllowedTypes('logger', ['\Psr\Log\LoggerInterface'])
            ->setAllowedTypes('version', ['string', 'integer'])
            ->setAllowedTypes('guzzleOptions', ['array']);

        return $resolver->resolve($options);
    

    /**
     * @param Client $client
     */
    private function buildDescriptions(Client $client)
    
        $description = \GuzzleHttp\json_decode(
            file_get_contents(__DIR__.'/Resources/service_description-v'.$this->options['version'].'.json'),
            true
        );

        $base = [
            'baseUri' => $this->options['apiUrl'],
            'version' => $description['version'],
            'models'  => $this->prepareModels($description['models']),
        ];
        foreach ($description['operations'] as $category => $operations) 
            $this->categories[$category] = new OverriddenGuzzleClient(
                $client,
                new Description(array_merge($base, ['operations' => $this->prepareOperations($operations)])),
                function ($res, $req, $com) use ($category, $description) 
                    return $this->convertResponseToResult($category, $description, $res, $com);
                ,
                $category
            );
        
    

    /**
     * @param string            $category
     * @param array             $description
     * @param ResponseInterface $response
     * @param CommandInterface  $command
     *
     * @throws \Exception
     *
     * @return Result|mixed
     *
     * @internal param RequestInterface $request
     */
    private function convertResponseToResult(
        $category,
        array $description,
        ResponseInterface $response,
        CommandInterface $command
    ) 
        if ($response->getStatusCode() >= 400) 
            throw new \Exception($response->getBody()->__toString(), $response->getStatusCode());
        

        $operation = $description['operations'][$category][$command->getName()];
        if (!isset($operation['responseTypes']) || count($operation['responseTypes']) === 0) 
            try 
                $content = $response->getBody()->__toString();
                if (empty($content)) 
                    $content = '';
                

                return new Result(json_decode($content, true));
             catch (\Exception $e) 
                dump($response->getBody()->__toString());

                throw $e;
            
        

        $data         = json_decode($response->getBody()->__toString());
        $array        = strpos($operation['responseTypes'][0]['type'], 'Array') !== false;
        $responseType = $operation['responseTypes'][0]['type'];
        if ($array) 
            $matches = [];
            preg_match('/Array<(.+)>/', $responseType, $matches);
            $responseType = $matches[1];
        

        $firstType = explode('/', $this->dashesToCamelCase($responseType, true));
        $class     = $this->mapBadDocs(
            sprintf(
                '\\RestCord\\Model\\%s\\%s',
                ucwords($firstType[0]),
                ucwords($firstType[1])
            )
        );

        if (!class_exists($class)) 
            return new Result($data);
        
        if ($data === null) 
            return new Result([]);
        

        $mapper                   = new \JsonMapper();
        $mapper->bStrictNullTypes = false;

        if ($array) 
            return array_map(
                function ($item) use ($class, $mapper) 
                    return $mapper->map($item, new $class());
                ,
                $data
            );
        

        return $mapper->map($data, new $class());
    

    private function dashesToCamelCase($string, $capitalizeFirstCharacter = false)
    
        $str = str_replace(' ', '', ucwords(str_replace('-', ' ', $string)));

        if (!$capitalizeFirstCharacter) 
            $str[0] = strtolower($str[0]);
        

        return $str;
    

    private function mapBadDocs($cls)
    
        switch ($cls) 
            case 'Channel\Invite':
            case '\RestCord\Model\Channel\Invite':
            case '\RestCord\Model\Guild\Invite':
                return '\RestCord\Model\Invite\Invite';
            case '\RestCord\Model\Guild\GuildChannel':
                return '\RestCord\Model\Channel\GuildChannel';
            case '\RestCord\Model\Guild\User':
            case '\RestCord\Model\Channel\User':
                return '\RestCord\Model\User\User';
            default:
                return $cls;
        
    

    /**
     * @param array $operations
     *
     * @return array
     */
    private function prepareOperations(array $operations)
    
        foreach ($operations as $operation => &$config) 
            $config['uri'] = ltrim($config['url'], '/');
            unset($config['url']);

            $config['httpMethod'] = strtoupper($config['method']);
            unset($config['method']);

            if (isset($config['responseTypes']) && count($config['responseTypes']) === 1) 
                $class = ucwords($config['resource']).'\\';
                $class .= str_replace(' ', '', ucwords($config['responseTypes'][0]['name']));

                $config['responseModel'] = $class;
             else 
                $config['responseModel'] = 'getResponse';
            

            if (isset($config['parametersArray']) && $config['parametersArray']) 
                $config['type'] = 'array';
            
            unset($config['parametersArray']);

            foreach ($config['parameters'] as $parameter => &$parameterConfig) 
                $this->updateParameterTypes($parameterConfig);
                if (!isset($parameterConfig['required'])) 
                    $parameterConfig['required'] = false;
                
            
        

        return $operations;
    

    /**
     * @param array $parameterConfig
     */
    private function updateParameterTypes(array &$parameterConfig)
    
        if ($parameterConfig['type'] === 'snowflake') 
            $parameterConfig['type'] = 'integer';
        

        if ($parameterConfig['type'] === 'bool') 
            $parameterConfig['type'] = 'boolean';
        

        if ($parameterConfig['type'] === 'file contents') 
            $parameterConfig['type'] = 'string';
        

        if (stripos($parameterConfig['type'], 'object') !== false) 
            $parameterConfig['type'] = 'array';
        
    

    /**
     * @return string
     */
    private function getVersion()
    
        return trim(file_get_contents(__DIR__.'/../VERSION'));
    

    /**
     * @param array $toParse
     *
     * @return array|mixed
     */
    private function prepareModels(array $toParse)
    
        $models = [
            'getResponse' => [
                'type'                 => 'object',
                'additionalProperties' => [
                    'location' => 'json',
                ],
            ],
        ];

        foreach ($toParse as $category => $m) 
            foreach ($m as $name => $model) 
                $class          = ucwords($category).'\\'.ucwords($name);
                $models[$class] = [
                    'type'                 => 'object',
                    'properties'           => [],
                    'additionalProperties' => [
                        'location' => 'json',
                    ],
                ];

                foreach ($model['properties'] as $n => $property) 
                    if ($property['type'] !== 'array' && $property['type'] !== 'object') 
                        $models[$class]['properties'][$n] = [
                            'type'     => $property['type'],
                            'location' => 'json',
                        ];
                    
                
            
        

        // Maps!
        $models['Guild\\Channel'] = $models['Channel\\Channel'];

        return $models;
    

    /**
     * @param string $tokenType
     * @param string $token
     *
     * @return string
     */
    private function getAuthorizationHeader($tokenType, $token)
    
        switch ($tokenType) 
            default:
                $authorization = 'Bot ';
                break;
            case 'OAuth':
                $authorization = 'Bearer ';
        

        return $authorization.$token;
    

对于 __DIR__.'/Resources/service_description-v'.$this-&gt;options['version'].'.json' json 文件,请参阅 pastebin https://pastebin.com/hZURQJkD

【问题讨论】:

其中哪一行是第 306 行? 该错误似乎不一定是因为 GuzzleHttp 而发生,而是因为您的“restcord”库试图将空字符串解码为有效的 JSON。 你为什么要命名json_decode 对不起,我不知道,这个脚本是我朋友写的。 @fyrye,谢谢现在它正在工作,我使用的是旧的 api。我刚刚用新的restcord替换了旧的restcord,现在它正在工作。谢谢。 【参考方案1】:

解决方案:我使用的是旧的 api,我用新的 restcord 替换了旧的 restcord,现在一切正常。

【讨论】:

以上是关于如何解决此解码和语法错误的主要内容,如果未能解决你的问题,请参考以下文章

如何解决 JAVA SQL 语法错误:错误代码 1064

如何解决 OleDb 错误“FROM 子句中的语法错误”?

如何解决 MySql 中的 PARTITION BY 语法错误

运行.kv文件时,我不断收到语法错误。我该如何解决? [关闭]

JSON 意外语法错误 - 日期解析/编码/解码

如何解决-的OPEN语句中的语法错误?