微信小程序的请求(wx.request)默认用 application/x-www-form-urlencoded,参数是键值对,里面的字符串会被 URL 编码。服务器端如果没有正确 urldecode() 或处理,字符串里的转义就被保留。

案例1:

string(615) “”[{\\”id\\”:3,\\”admin_id\\”:1,\\”project_id\\”:1,\\”name\\”:\\”浜у搧2\\”,\\”thumb\\”:\\”about_pic/241129/67493ec54ed05.png\\”,\\”product_type\\”:0,\\”stock\\”:999,\\”market_price\\”:\\”9600.00\\”,\\”title\\”:\\”浜у搧2\\”,\\”thumb_url\\”:\\”http://test.com/upfile/about_pic/241129/67493ec54ed05.png\\”,\\”tags\\”:[],\\”price\\”:\\”9600.00\\”,\\”quantity\\”:2,\\”totalprice\\”:\\”19200.00\\”}]””

问题:

  • 外面多了一层/两层引号"" ... ""),json 语法要求最外层直接是 [{",不能是 ""[

  • 内部双引号被反斜杠转义 成了 \",并且还可能因为多重处理变成 \\",产生不合法的转义序列。

  • 可能还包含 HTML 实体(")或 URL 编码(%5B)等。

这些都会让 json_decode()Syntax error, malformed JSON

1、使用

/**
 * 兼容性强的 JSON 还原解析(处理多层转义 / HTML 实体 / urlencode 等)
 * 返回 array|object|null
 */
function robust_json_decode($raw) {
    if ($raw === null) return null;
    $original = $raw;
    // 尝试次数
    for ($i = 0; $i < 6; $i++) {
        // 1. 去除首尾空白
        $s = trim($raw);
        // 2. HTML 实体还原(处理 &quot; 等)
        $s = html_entity_decode($s, ENT_QUOTES | ENT_HTML5, ‘UTF-8’);
        // 3. 如果像 URL encoded(含 %5B/%7B),尝试 urldecode
        if (strpos($s, ‘%5B’) !== false || strpos($s, ‘%7B’) !== false || strpos($s, ‘%22’) !== false) {
            $s = urldecode($s);
        }
        // 4. 剥离前后非 JSON 有效字符,直到遇到 { [ 或 “
        while ($s !== ” && !in_array($s[0], [‘{‘,'[‘,'”‘], true)) {
            $s = substr($s, 1);
        }
        while ($s !== ” && !in_array(substr($s, -1), [‘}’,’]’,'”‘], true)) {
            $s = substr($s, 0, -1);
        }
        // 5. 如果最外层被双引号包了(整个 JSON 又被当字符串包了一层),去掉外层一对引号
        if (strlen($s) >= 2 && $s[0] === ‘”‘ && substr($s, -1) === ‘”‘) {
            $s = substr($s, 1, -1);
        }
        // 6. 去反斜杠(模拟 stripslashes 的多次效果),并把 \” 换回 “
        //    循环几次以处理 \\\” 等多重转义
        $prev = null;
        for ($k = 0; $k < 6; $k++) {
            $prev = $s;
            // 先把常见的 \\ -> \ 再把 \” -> “
            $s = str_replace(‘\\\\’, ‘\\’, $s);
            $s = str_replace(‘\\”‘, ‘”‘, $s);
            $s = str_replace(“\\'”, “‘”, $s);
            $s = html_entity_decode($s, ENT_QUOTES | ENT_HTML5, ‘UTF-8’); // 再次解实体
            if ($s === $prev) break;
        }
        // 7. 再次去除外层的空白/控制字符
        $s = trim($s, “\x00..\x1F”);
        // 8. 尝试 json_decode
        $decoded = json_decode($s, true);
        if ($decoded !== null) {
            return $decoded;
        }
        // 有时第一次 decode 后返回的是字符串(内层仍然是 JSON),
        // 或者 decode 失败但我们可以对 s 做些轻微替换再尝试
        // 准备下次循环的输入:把 \” 进一步替换成 “
        $raw = str_replace(‘\\”‘, ‘”‘, $s);
    }
    // 解析失败,记录诊断(便于排查)
    // $err = function_exists(‘json_last_error_msg’) ? json_last_error_msg() : json_last_error();
    // p(“robust_json_decode_php failed. json_error={$err}. original_sample=” . substr((string)$original, 0, 200));
    return null;
}

php解析ajax传输的json null

作者 admin

百度广告效果展示