PHP项目JSON解析失败如何捕获

wen PHP项目 25

本文目录导读:

PHP项目JSON解析失败如何捕获

  1. 使用 json_last_error() 和 json_last_error_msg()
  2. 封装成函数
  3. 使用 try-catch 配合异常处理
  4. 使用 try-catch 块(PHP 7.3+)
  5. 完整的JSON验证和转换函数
  6. 使用中间件方式(适用于框架)
  7. 最佳实践建议

在PHP项目中,处理JSON解析失败的情况,可以使用以下几种方法来捕获错误:

使用 json_last_error() 和 json_last_error_msg()

<?php
$jsonString = '{"name": "John", age: 30}'; // 错误的JSON格式
$data = json_decode($jsonString);
if (json_last_error() !== JSON_ERROR_NONE) {
    $errorCode = json_last_error();
    $errorMessage = json_last_error_msg();
    echo "JSON解析失败!\n";
    echo "错误代码: " . $errorCode . "\n";
    echo "错误信息: " . $errorMessage . "\n";
}
?>

封装成函数

<?php
function safeJsonDecode($json, $assoc = false, $depth = 512, $options = 0) {
    $data = json_decode($json, $assoc, $depth, $options);
    if (json_last_error() !== JSON_ERROR_NONE) {
        switch (json_last_error()) {
            case JSON_ERROR_DEPTH:
                throw new \Exception('超出最大堆叠深度');
            case JSON_ERROR_STATE_MISMATCH:
                throw new \Exception('JSON格式错误或语法错误');
            case JSON_ERROR_CTRL_CHAR:
                throw new \Exception('发现意外控制字符');
            case JSON_ERROR_SYNTAX:
                throw new \Exception('JSON语法错误');
            case JSON_ERROR_UTF8:
                throw new \Exception('字符编码错误');
            default:
                throw new \Exception('未知JSON错误: ' . json_last_error_msg());
        }
    }
    return $data;
}
// 使用示例
try {
    $jsonString = '{"name": "John", "age": 30}'; // 正确的JSON
    $data = safeJsonDecode($jsonString);
    print_r($data);
} catch (\Exception $e) {
    echo "捕获到异常: " . $e->getMessage() . "\n";
}
?>

使用 try-catch 配合异常处理

<?php
class JsonParseException extends \Exception {
    private $jsonInput;
    public function __construct($message, $jsonInput = '', $code = 0) {
        parent::__construct($message, $code);
        $this->jsonInput = $jsonInput;
    }
    public function getJsonInput() {
        return $this->jsonInput;
    }
}
function parseJsonSafely($jsonString) {
    $data = json_decode($jsonString, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new JsonParseException(
            json_last_error_msg(),
            $jsonString,
            json_last_error()
        );
    }
    return $data;
}
// 使用示例
try {
    $jsonString = '{"name": "John", "data": [1, 2, 3}'; // 错误的JSON
    $result = parseJsonSafely($jsonString);
    var_dump($result);
} catch (JsonParseException $e) {
    echo "JSON解析失败: " . $e->getMessage() . "\n";
    echo "原始输入: " . $e->getJsonInput() . "\n";
    echo "错误代码: " . $e->getCode() . "\n";
    // 记录日志
    error_log("JSON Parse Error: " . $e->getMessage() . " Input: " . $e->getJsonInput());
    // 返回默认值
    $result = [];
}
?>

使用 try-catch 块(PHP 7.3+)

<?php
// PHP 7.3 引入了 JSON_THROW_ON_ERROR 常量
try {
    $jsonString = '{"name": "John", "age": 30}'; // 错误的JSON
    $data = json_decode($jsonString, true, 512, JSON_THROW_ON_ERROR);
    print_r($data);
} catch (\JsonException $e) {
    echo "JSON解析错误: " . $e->getMessage() . "\n";
    echo "错误码: " . $e->getCode() . "\n";
    // 错误处理
    $data = ['default' => 'value']; // 使用默认值
}
?>

完整的JSON验证和转换函数

<?php
class JsonHandler {
    /**
     * 安全解析JSON字符串
     * 
     * @param string $jsonStr JSON字符串
     * @param bool $assoc 是否转换为关联数组
     * @param mixed $default 解析失败时返回的默认值
     * @return mixed
     */
    public static function safeDecode($jsonStr, $assoc = true, $default = null) {
        if (!is_string($jsonStr) || empty(trim($jsonStr))) {
            return $default;
        }
        $data = json_decode($jsonStr, $assoc);
        if (json_last_error() !== JSON_ERROR_NONE) {
            // 记录错误信息
            self::logError($jsonStr);
            // 尝试修复JSON
            $fixed = self::tryFixJson($jsonStr);
            if ($fixed !== null) {
                return json_decode($fixed, $assoc);
            }
            return $default;
        }
        return $data;
    }
    /**
     * 记录JSON错误日志
     */
    private static function logError($jsonStr) {
        $error = json_last_error_msg();
        $debugInfo = [
            'error' => $error,
            'input_length' => strlen($jsonStr),
            'input_preview' => substr($jsonStr, 0, 100),
            'timestamp' => date('Y-m-d H:i:s')
        ];
        error_log("JSON Parse Error: " . json_encode($debugInfo));
    }
    /**
     * 尝试修复常见的JSON错误
     */
    private static function tryFixJson($jsonStr) {
        // 尝试修复单引号代替双引号
        $fixed = preg_replace('/\'([^\']*)\'/', '"$1"', $jsonStr);
        // 尝试添加缺少的引号到键名
        $fixed = preg_replace('/(\w+):/i', '"$1":', $fixed);
        // 移除尾部逗号
        $fixed = preg_replace('/,\s*([\]}])/', '$1', $fixed);
        // 测试修复后的JSON
        json_decode($fixed);
        if (json_last_error() === JSON_ERROR_NONE) {
            return $fixed;
        }
        return null;
    }
}
// 使用示例
$json = '{"name": "John", age: 30}'; // 错误的JSON(age没有引号)
$result = JsonHandler::safeDecode($json, true, ['error' => '解析失败']);
print_r($result);
?>

使用中间件方式(适用于框架)

<?php
class JsonMiddleware {
    public function handleRequest($requestData) {
        try {
            $jsonData = json_decode($requestData, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                throw new \InvalidArgumentException('无效的JSON数据');
            }
            return $jsonData;
        } catch (\Exception $e) {
            // 返回标准错误响应
            return [
                'success' => false,
                'error' => [
                    'code' => 400,
                    'message' => '请求数据格式错误',
                    'details' => $e->getMessage()
                ]
            ];
        }
    }
}
?>

最佳实践建议

  1. 始终验证JSON格式:不要假设所有输入都是有效的JSON
  2. 使用异常处理:通过try-catch统一处理错误
  3. 记录日志:记录失败的JSON输入以便调试
  4. 提供默认值:解析失败时返回合理的默认值
  5. 考虑安全性:避免在错误信息中暴露敏感数据

选择哪种方法取决于你的具体需求和PHP版本,对于现代PHP项目(7.3+),推荐使用 JSON_THROW_ON_ERROR 配合 try-catch。

抱歉,评论功能暂时关闭!