You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

处理含JSON字段的CSV时反斜杠导致键值映射异常问题

问题:CSV含带反斜杠的JSON字段导致键值映射异常

我正在处理一个CSV文件,其中某列包含JSON格式数据,该JSON里部分字段带有反斜杠,导致后续键值映射出现问题。前两行数据处理正常,但从第三行开始,“Event Value”列的带反斜杠JSON数据引发了映射错误。

当前代码

$file_name = 'new_testing.csv';

$file_path = '/var/www/html/'.$file_name;

$file_content = file_get_contents($file_path);

$file = new SplFileObject($file_path);
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY);

// Read and skip the headers
$headers = $file->fgetcsv();

// Process the data
$chunkSize = 5000; // Set the desired chunk size
$loop = 0;

$chunkData = [];

while (!$file->eof()) {
    // Read the next chunk of lines
    for ($i = 0; $i < $chunkSize && !$file->eof(); $i++) {
        $line = $file->fgetcsv();
        if ($line) {
            // Sanitize each field in the line to remove backslashes and double quotes
            $line = array_map(function ($field) {
                return str_replace(['\', '&quot;'], '', $field);
            }, $line);

            // Adjust the number of elements in $line to match the number of headers
            if (count($line) < count($headers)) {
                // Fill missing values with null or empty strings
                $line = array_pad($line, count($headers), null);
            } elseif (count($line) > count($headers)) {
                // Trim extra values
                $line = array_slice($line, 0, count($headers));
            }

            // Combine headers and line values into an associative array
            $row = array_combine($headers, $line);
            $chunkData[] = $row;
        }
    }
}

echo "<pre>";
print_r($chunkData);

问题根源

SplFileObject::fgetcsv()默认解析逻辑会把反斜杠当作转义符,导致包含反斜杠的JSON字段被错误拆分,使$line数组元素数量和表头不匹配,最终array_combine抛出映射错误。另外,当前代码盲目删除反斜杠和引号的操作会直接破坏JSON结构,后续即使拆分正确也无法解析JSON。

解决方案

方案1:自定义CSV字段解析,保证字段完整性

绕过fgetcsv()的默认解析,用正则匹配正确拆分带特殊字符的字段:

$file = new SplFileObject($file_path);
$file->setFlags(SplFileObject::SKIP_EMPTY);
$headers = $file->fgetcsv();

$chunkData = [];
$chunkSize = 5000;

while (!$file->eof()) {
    for ($i = 0; $i < $chunkSize && !$file->eof(); $i++) {
        $line = $file->fgets();
        if (empty($line)) continue;
        
        // 正则匹配CSV字段,兼容带转义符的引号包裹字段
        preg_match_all('/(?:^|,)(?:"(?:\\\\.|[^"])*"|[^",]*)/', $line, $matches);
        $fields = array_map(function($field) {
            // 清理字段首尾的逗号和空白符
            $field = trim($field, ", \t\n\r");
            // 处理被引号包裹的字段,还原转义内容
            if (str_starts_with($field, '"') && str_ends_with($field, '"')) {
                $field = substr($field, 1, -1);
                $field = stripslashes($field);
            }
            return $field;
        }, $matches[0]);
        
        // 对齐字段数量与表头
        if (count($fields) < count($headers)) {
            $fields = array_pad($fields, count($headers), null);
        } elseif (count($fields) > count($headers)) {
            $fields = array_slice($fields, 0, count($headers));
        }
        
        // 可选:解析Event Value列的JSON
        $eventValueKey = array_search('Event Value', $headers);
        if ($eventValueKey !== false && !empty($fields[$eventValueKey])) {
            $fields[$eventValueKey] = json_decode($fields[$eventValueKey], true) ?: $fields[$eventValueKey];
        }
        
        $row = array_combine($headers, $fields);
        $chunkData[] = $row;
    }
}

echo "<pre>";
print_r($chunkData);

方案2:预处理CSV内容,修正转义逻辑

先修正CSV中JSON字段的转义问题,再用标准方法解析:

$file_content = file_get_contents($file_path);
// 确保JSON字段内的转义符被正确处理,避免CSV解析时拆分错误
$file_content = preg_replace_callback('/"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"/', function($matches) {
    return '"' . addslashes(stripslashes($matches[1])) . '"';
}, $file_content);

// 创建临时文件处理修正后的内容
$tempFile = tempnam(sys_get_temp_dir(), 'csv_fix_');
file_put_contents($tempFile, $file_content);

$file = new SplFileObject($tempFile);
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY);
$headers = $file->fgetcsv();

$chunkData = [];
$chunkSize = 5000;

while (!$file->eof()) {
    for ($i = 0; $i < $chunkSize && !$file->eof(); $i++) {
        $line = $file->fgetcsv();
        if ($line) {
            // 解析Event Value列的JSON
            $eventValueKey = array_search('Event Value', $headers);
            if ($eventValueKey !== false && !empty($line[$eventValueKey])) {
                $line[$eventValueKey] = json_decode($line[$eventValueKey], true) ?: $line[$eventValueKey];
            }
            
            // 对齐字段数量
            if (count($line) < count($headers)) {
                $line = array_pad($line, count($headers), null);
            } elseif (count($line) > count($headers)) {
                $line = array_slice($line, 0, count($headers));
            }
            
            $row = array_combine($headers, $line);
            $chunkData[] = $row;
        }
    }
}

unlink($tempFile); // 删除临时文件
echo "<pre>";
print_r($chunkData);

注意事项

  • 禁止盲目删除反斜杠或引号,这会破坏JSON结构,导致后续无法解析。
  • 优先保证CSV字段拆分的正确性,再处理JSON内容的解析。

内容的提问来源于stack exchange,提问作者Siddhart hundare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:14:56