不能json_decode一个GET参数

时间:2013-09-10 20:50:43

标签: php ajax json

所有

我正在尝试将字符串化的json对象作为GET参数传递,但接收URL似乎无法对其进行解码,我不确定原因。

以下是相关代码:

客户端Json对象生产(工作正常):

function createJson(){
// This works fine.  It creates a json objects with three elements, the third being an array.
//(omitted code for brevity)
  return jsonData;
}

客户端ajax调用(工作正常):

function recordSetGet(jsonData){
  request = createRequest();
  var rawSet=JSON.stringify(jsonData);
  var encodedSet=encodeURIComponent(rawSet);
  var params="set="+encodedSet;
  var url= "Ajax_recordSetGet.php?"+params;
  request.open("GET", url, true);
  request.onreadystatechange = function(){}
  request.send(null);
}

这会产生以下网址:Ajax_recordSetGet.php?set=%7B%22setTitle%22%3A%22test%22%2C%22setTags%22%3A%22test%20%22%2C%22set%22%3A%5B%7B%22first%22%3A%22Joe%22%2C%22last%22%3A%22Doe%22%2C%22checked%22%3Atrue%7D%5D%7D"

服务器端处理:

<?php
header('Content-Type:text/html; charset=UTF-8');  
if(!session_id()){
  session_start();
}
if(isset($_GET['set'])){
  $set=$_GET['set'];//This is the URI encoded string
  var_dump ($set);
  var_dump (json_decode($set));
  var_dump ("Json last error is ".json_last_error());
}
?>

var_dumps的结果是: string '{"setTitle":"test","setTags":"test ","set":[{"first":"Joe","last":"Doe","checked":true}]}"' (length=90)
null
string 'Json last error is 4' (length=20)

那么为什么json_decode()在这里失败了? json_last_error()结果表明语法错误。

编辑:请注意,如果我发送一个非编码字符串,json_decode也会失败:
如果我构建param字符串而不对它进行编码:

var rawSet=JSON.stringify(jsonData);
var params="set="+rawSet;
var url= "Ajax_recordSetGet.php?"+params;

然后网址变为Ajax_recordSetGet.php?set={"setTitle":"test","setTags":"test ","set":[{"first":"Joe","last":"Doe","checked":true}]}"

接收URL var_dump产生相同的错误:
string '{"setTitle":"test","setTags":"test ","set":[{"first":"Joe","last":"Doe","checked":true}]}"' (length=90)
null
string 'Json last error is 4' (length=20)

2 个答案:

答案 0 :(得分:1)

http://php.net/manual/en/function.urldecode.php

  

superglobals $ _GET和$ _REQUEST已经解码。在$ _GET或$ _REQUEST中的元素上使用urldecode()可能会产生意外和危险的结果。

尝试不同的方式。我建议对json字符串进行base64编码。

而不是:

var rawSet=JSON.stringify(jsonData);
var encodedSet=encodeURIComponent(rawSet);
var params="set="+encodedSet;
var url= "Ajax_recordSetGet.php?"+params;

这样做:

var rawSet=JSON.stringify(jsonData);
var encodedSet=btoa(rawSet);
var params="set="+encodedSet;
var url= "Ajax_recordSetGet.php?"+params;

但要注意caveats

在您的服务器端:

$decodedSet=json_decode(base64_decode($set));

答案 1 :(得分:1)

我不知道为什么,但是您的网址中有一个尾随双引号会混淆JSON解码过程。

...%7D%5D%7D"   <- Trailing double quote

此引号也显示在转储set变量中:

...true}]}"' (length=90) <- double quote is inside the string, the single quote is part of the var_dump output.

这个双引号必须在Javascript代码中引入,虽然我看不到应该发生的地方。但是你的调试应该在系统的那个部分进行。

请注意,您不得对作为“set”参数传递的字符串进行urldecode,因为PHP已经为您完成了解码。但是使用尾随双引号,您无法调用json_decode()

作为概念的快速证明,请在解码前尝试在PHP代码中使用$set = rtrim($set, '"')以删除该引号字符。