【发布时间】:2017-08-17 14:55:53
【问题描述】:
我正在使用 MariaDB 的 COLUMN_JSON() 函数。正如this bug 说明的那样,该函数正确地转义了双引号,而不是应该编码/转义的其他字符。
这是一个愚蠢的示例查询,用于演示如何创建 JSON 列。
SELECT CONCAT('[', GROUP_CONCAT(COLUMN_JSON(COLUMN_CREATE(
'name', `name`,
'value', `value`
)) SEPARATOR ','), ']') AS `json`
FROM `settings`
如果name 或value 包含无效的JSON 字符,json_decode 将失败。
我编写了一个 PHP 函数来转义/编码来自查询的值,但似乎应该有更好的方法。
/**
* Makes sure the JSON values built by COLUMN_JSON() in MariaDB are safe for json_decode()
* Assumes that double quotes are already escaped
*
* @param string $mysql_json
* @return string
*/
public static function jsonEscape($mysql_json)
{
$rtn = '';
for ($i = 0; $i < strlen($mysql_json); ++$i) {
$char = $mysql_json[$i];
if (($char === '\\') && ($mysql_json[$i + 1] !== '"')) {
// escape a backslash, but leave escaped double quotes intact
$rtn .= '\\\\';
} elseif (($ord = ord($char)) && ($ord < 32)) {
// hex encode control characters (below ASCII 32)
$rtn .= '\\u' . str_pad(dechex($ord), 4, '0', STR_PAD_LEFT);
} else {
$rtn .= $char;
}
}
return $rtn;
}
像这样逐个字符地检查字符串效果不佳。也许有更高效的字符串替换或正则表达式?
【问题讨论】:
-
我不认为这是一个错误。 Claudio Galdiolo 显示的问题是他的查看器没有逃避
\n,问题不在Maria DB 中。换行符是\n或\u000A,但肯定不是\\n。 -
如果值具有控制字符,PHP 的
json_decode()将阻塞来自 MariaDB 的COLUMN_JSON()函数的值。我已经验证了该行为,并在寻找解决方案时发现了错误报告。 -
让我们假设错误存在。试试看
str_replace或strpos的实现是否更快。请注意str_replace接受value->replacements的数组。对于 strpos,您需要循环播放所有 32 个字符。 -
@RyanVincent - 没有“原始字符串” - COLUMN_JSON() 正在使用数据库列中的值创建字符串。列中的值不是 JSON 安全的。它们包含引号、回车符等。
-
@RyanVincent - 重点。添加了示例查询。