如何在php json_encode之前正确地转换格式错误的json输入中的双引号

时间:2019-03-14 12:22:46

标签: php json regex escaping

我在处理之前要导入一个大的json文件。我不控制此文件的内容,并且json的转义方式不正确,导致在双引号内包含双引号的情况。 例如:

/...../
"productdiploma" : [],
"productcursus" : ["Méthodes"],
"productpublishedonsite" : false,
"productpublishedonkne" : false,
"productypologyparentality" : [ {
    "productmediaformat" : "01- Livre",
    "producttechformat" : "50- Grand format - "Autre"",
    "productparent" : ""
    }],
"productparentwork" : [ {
    "productparentworkid" : "1000248048",
    "productparentworktitle" : "TRAVAILLER EN FRANCAIS "EN ENTREPRISE" 2007"
/...../

在我的导入中,使用file_get_contents()将文件视为非常大的字符串。我可能在那里需要一个preg_replace()或preg_filter(),但是我无法弄清楚我需要哪种模式来查找和转义带有双引号的\“。那里有任何帮助/想法吗?

(并在下面用anwser中的注释对shibon进行查看,以了解为什么它不是重复的)

2 个答案:

答案 0 :(得分:1)

我建议您在这里需要其他方法。将文件作为一个大字符串加载意味着几乎不可能知道需要使用双引号,而不需要使用双引号。我会采用一种允许您逐行阅读详细内容的方法;

<?php
$file = fopen("test.txt","r");

while(! feof($file))
  {
  $line = fgets($file);
  }

fclose($file);
?>

这样,您可以像这样测试每个的右侧;

$partToTest = explode($line, ':')[1];

知道对于所有带引号的项目(即没有数组),它们应该是每行的第一个和最后一个字符。因此,您可以按照以下方式进行操作:

如果零件带有引号,请删除第一个和最后一个

if($partToTest.substr($line, 0, -1) === "\""))
    $partToTest  = substr($line, 0, -1); # removes the last quote
    $partToTest  = substr($line, 1, 0); # removes the first quote

用\“

替换所有剩余的引号
    $partToTest  = str_replace("\"", "\\\""); # escape remaining quotes

在新引号前后附加新引号,以替换我们删除的引号

    $partToTest = "\"" . $partToTest . "\""; 

将线重新放在一起。

    $line = explode($line, ':')[0] + $partToTest;
}

诚然,我的php技能不是最好的,所以可能有更简单的方法来做到这一点,但是原理应该起作用。

答案 1 :(得分:1)

我根据@lewis的想法设法编写了这段代码:

$content = '';
while(! feof($infile) )
  {
    // reset line values at each iteration.
    $final_line = '';
    $test = array();

    // get the next line
    $line = trim(fgets($infile));

    // test if the line is splitable, else, white as is ({, [ etc...])
    if(strpos($line,'" : "')) {

        // split the line at quote+space+':'.space+quote to avoid splitting strings containing just ' : ' (not fool proof as a string might still contain '" : "' and split, but works in my case)

        $test = explode('" : "',$line) ;
        // add the final quote that we just stripped in the splitting to the key 
        $key =  $test[0].'"';

        // test if the line ends with a comma or not to decide at which position to remove the last quote 
        if( strpos($test[1], '",') == (strlen($test[1])-2) ){
            $val = substr($test[1],0,-2);
            $comma = ','; // store a comma for latter use
        } else {
            $val = substr($test[1],0,-1);
            $comma = '';
        }
        // no need to remove remove the fist quote it's been taken care of at splitting

        // replace the double quotes inside the trimmed string
        $val =  str_replace('"','\"', trim($val));
        // reassemble the corrected line
        $final_line = $key . ' : "' . $val . '"'. $comma ."\n";
    } else {
        $final_line = $line ."\n";
    }

    //store the line for later treatment
    $content .= utf8_encode($final_line);
  }

这可以完成这项工作,尽管它要慢得多,而且如果该行在我要测试的部分中包含'“:”'字符串,那么拆分中仍然有出错的余地,但这还是可以解决的:)< / p>