本文目录导读:

- 使用 json_last_error() 和 json_last_error_msg()
- 封装成函数
- 使用 try-catch 配合异常处理
- 使用 try-catch 块(PHP 7.3+)
- 完整的JSON验证和转换函数
- 使用中间件方式(适用于框架)
- 最佳实践建议
在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()
]
];
}
}
}
?>
最佳实践建议
- 始终验证JSON格式:不要假设所有输入都是有效的JSON
- 使用异常处理:通过try-catch统一处理错误
- 记录日志:记录失败的JSON输入以便调试
- 提供默认值:解析失败时返回合理的默认值
- 考虑安全性:避免在错误信息中暴露敏感数据
选择哪种方法取决于你的具体需求和PHP版本,对于现代PHP项目(7.3+),推荐使用 JSON_THROW_ON_ERROR 配合 try-catch。