将 CR/LF 保存在 json 数据中

Posted

技术标签:

【中文标题】将 CR/LF 保存在 json 数据中【英文标题】:Saving CR/LF in json data 【发布时间】:2014-11-19 01:12:54 【问题描述】:

我正在将表数据保存到 json 对象。表格数据来自表格单元格中的 txt 输入和文本区域。

我在保存 textarea 数据的 JSON 元素中遇到了 CR/LF 字符的问题。 JSON数据很好地保存到数据库中,但是当我将它传递回使用该数据填充表的jQuery函数时,我得到了:

SyntaxError: JSON.parse: bad control character in string literal at line 1 column 67 of the JSON data
var array = JSON.parse(notes),

在控制台中。

我将 JSON 数据放在 Notepad++ 中并显示所有字符,CR/LF 位于第 67 列。

这是我正在使用的 JSON 数据示例:

[["","","",""],["","9/23/14","",""],["","30789 detail, x_vendor_no**CR/LF HERE**
20597 header","",""],["","99 del invalid x_vendor_no","",""],["","30780","",""],["","","",""],["","","",""],["","","",""]]

有没有办法在数据中允许 CR/LF?

更新 11684 建议使用 replace 删除 CRLF 的 \r 部分将不起作用。原因如下:

以下是使用 JSON 数据的完整函数: (已更新以使用下面的更新 #2 代码)

function PopulateTaskTableWithNotes(tableID,notesArray) 
    // JSON parse removed per answer suggestion
    var r, c, note;

    for (r = 0; r < notesArray.length; ++r) 
        for (c = 0; c < notesArray[r].length; ++c) 
            note = notesArray[r][c];
        $('#' + tableID + ' tr:nth-child(' + (r + 1) + ') td:nth-child(' + (c + 1) + ')').children(':first-child').val(note);
        
    

我仍然在尝试解析 JSON 数据的行上遇到错误。替换函数显然无法在数组元素中“找到”字符。

更新 #2 这是我创建数组的方式:

var siteID = $('#ddlUserSites option:selected').val(),
    numRows = $('#' + tableID + ' tr').length,
    numCols = $('#' + tableID).find('tr:first th').length,
    notesArray = new Array(numRows),
    rowNum = 1,
    note = '',
    colNum;

while (rowNum <= numRows) 
    notesArray[rowNum] = new Array(numCols);

    // Reset colNum for next row iteration
    colNum = 1;
    while (colNum <= numCols) 
        note = '';

        if ($('#' + tableID + ' tr:nth-child(' + rowNum + ') td:nth-child(' + colNum + ')').children(':first-child').is('input,textarea')) 
            note = $('#' + tableID + ' tr:nth-child(' + rowNum + ') td:nth-child(' + colNum + ')').children(':first-child').val();
        
        notesArray[rowNum][colNum] = note;
        //console.log('Note for rowNum ' + rowNum + ', colNum ' + colNum + ': ' + note);
        colNum++;
    
    // Remove first element in current row array
    notesArray[rowNum].shift();
    rowNum++;

// Remove first element in array
notesArray.shift();
JSON.stringify(notesArray); // Added per an answer here
console.log('Final notesArray: ' + $.toJSON(notesArray));

$.ajax(
    data: saveTaskNotes: 'true', userID:userID, siteID:siteID, taskTable:tableID, notes:notesArray,
    success: function(data) 
        console.log('Save task notes data: ' + data);
    
);

“Final notesArray”控制台输出看起来不错,但现在,添加了 stringify,上面的函数 (PopulateTaskTableWithNotes) 控制台输出显示它正在读取数组中的每个字符作为一个单独的元素!

也许这也有帮助,至于创建和读取函数之间的数据发生了什么:数组被保存到单个 mysql 数据库字段,然后通过 $.ajax() 检索 PopulateTable 函数(on两端)。

话虽如此,我是否需要查看我对 php 代码中的数组所做的操作?

更新 #3 这是接收数据并写入 MySQL 数据库的 PHP 函数:

function SaveTaskNotes($userID,$siteID,$taskTable,$notes) 
    $notes = json_encode($notes);
    $insertUpdateTaskNotesResult = '';
    $insertTaskNotes = "INSERT INTO userProgress (userProgressUserID,userProgressSiteID,userProgressNotesTable,userProgressNotes) values ($userID,$siteID,'" . $taskTable . "','" . $notes . "')";
    $log->lwrite('$insertTaskNotes: ' . $insertTaskNotes);
    $resultInsertTaskNotes = @mysqli_query($dbc,$insertTaskNotes);
    if ($resultInsertTaskNotes) 
        $insertUpdateTaskNotesResult = 'insertTaskNotesSuccess';
     else 
        if (mysqli_error($dbc) != '') 
            $log->lwrite('INSERT TASK NOTES: An error occurred while attempting to add the task notes. Query: ' . $insertTaskNotes . ', mysqli_error: ' . mysqli_error($dbc));
        
        $insertUpdateTaskNotesResult = 'insertTaskNotesFail';
    
    echo $insertUpdateTaskNotesResult;

这是从数据库中获取数据并将其发送到上述 $.ajax 函数的函数:

function GetUserTaskNotes($userID,$siteID,$taskTableID) 
    $queryGetUserTaskNotes = "SELECT userProgressNotes FROM userProgress WHERE userProgressUserID = $userID AND userProgressSiteID = $siteID AND userProgressNotesTable = '" . $taskTableID . "'";
    $log->lwrite('$queryGetUserTaskNotes: ' . $queryGetUserTaskNotes);
    $resultGetUserTaskNotes = @mysqli_query($dbc,$queryGetUserTaskNotes);
    if ($resultGetUserTaskNotes) 
        $taskNotes = mysqli_fetch_assoc($resultGetUserTaskNotes);
        $log->lwrite('Retrieved $taskNotes[\'userProgressNotes\']: ' . $taskNotes['userProgressNotes']);
        echo $taskNotes['userProgressNotes'];
     else 
        if (mysqli_error($dbc) != '') 
            $log->lwrite('GET TASK NOTES: An error occurred while attempting to retrieve the task notes. Query: ' . $queryGetUserTaskNotes . ', mysqli_error: ' . mysqli_error($dbc));
        
        echo 'getTaskNotesFail';
    

在保存和获取函数中,$log 输出显示数组永远不会改变(使用上面的 js/php 代码),将数组粘贴到 notepad++ 表明 CR/LF 始终存在。

【问题讨论】:

快速修复:notes.replace("\r\n", "");。不过我不建议这样做。 或者只是notes.replace("\r", ""); @11684:我希望找到一种解决方案,可以让我保留这些新行,或者以某种方式用用户输入的新行重新填充 textarea。 是的,当我编写 cmets 时,我还没有看到您的编辑,包括示例数据,并且我(错误地)假设换行符不是数据的一部分,而是介于值之间(所以,安全移除)。替代方案:notes.replace("\r\n", "\n");。 Windows 是唯一使用\r\n 而不是\n 进行换行的(主流)操作系统,因此浏览器不会(不应该)介意。 @11684:没用 - 请参阅我的问题的更新部分。 【参考方案1】:

不要使用JSON.parse,数据已经是JSON,javascript可以使用它。

只有在传递字符串时才需要它,想象一下 JSON.parse() 就像 string2json() 一样。

我认为这可能已经解决了您的问题,我从来没有遇到过换行符的问题。

正如Luis所说,除了JSON.parse之外,问题不在于您的客户端(Javascript,jQuery),而是提供站点错误。

PHP 示例:

<?php
echo json_encode(array("test" => "


x"));

PHP 正确地转义了字符:

"test":"\r\n\r\n\r\nx"

但是您的数据源提供了格式错误的 JSON。

要修复 JSON 问题,请使用准备好的语句或使用:

$notes = str_replace('\', '\\', json_encode($notes)); // in SaveTaskNotes

【讨论】:

您说:“不要使用 JSON.parse,数据已经是 JSON,Javascript 可以使用它。”虽然这是有道理的,并且控制台显示当我从 php 脚本进入函数时查看它时的情况,如果我不使用解析,则数组被解释为每个字符都是它自己的数组元素.此外,当其中没有换行符时使用 JSON.parse(notesArray) 就可以了!那么解决办法是什么? 请在 ajax 调用之后添加 PHP 代码(发布 json)和 PHP 代码,然后再尝试对 JSON 进行 ajax。在数据库交互之前或之后出现问题。 @eventide 在数据库中,通过 phpMyAdmin,在userProgressNotes 列中,您看到的是字面意义上的\r\n,还是看到了真正的换行符? userProgressNotes 包含 JSON 对吗? phpMyAdmin 显示带有实际换行符的字段内容 - 而不是“\r\n”。 userProgressNotes 是一个 varchar(5000) 字段。 没问题!我不确定准备好的语句是否会阻止新行字符被转义......但它们确实更好。祝你好运,玩得开心编码:)【参考方案2】:

好吧,错误在于输入数据(显示有问题)。 JSON 字符串中的文字内不能有 CR 或 LF。你可以拥有的是字符转义为\r\n。问题在另一方面,转义代码被实际字符替换,因此完整的 JSON 字符串变得无效。

【讨论】:

有道理。添加数组的元素时,我将如何转义 CR 和 LF? JSON.stringify(values); 应用于整个数据,而不是按部分超过元素。你会得到一个唯一的字符串来编码所有的东西。你也会得到正确编码的 cr & lf。有很多例子。 -1--2- 在创建数组时遍历表数据后,我在数组上使用了 JSON.stringify。控制台输出看起来不错(与添加 stringify 之前非常相似)。根据您的建议,我从读取数组的位置删除了 json.parse 。那个时候我没有收到错误,但是每次迭代数组元素时的控制台输出显示它正在将每个字符作为数组元素分离出来!我已将我的数组构建脚本添加到我的问题中。

以上是关于将 CR/LF 保存在 json 数据中的主要内容,如果未能解决你的问题,请参考以下文章

多部分/表单数据请求的 Indy MIME 解码返回尾随 CR/LF

CR LF CR/LF

Tibco Designer -- 换行符LF转CR/LF

CRLF、CR、LF详解

批处理文件+将LF转换为CR + LF

将 CR/LF 插入文本区域