【问题标题】:PHP json_encode on a SOAP response returns array if multiple, but object if single?SOAP响应上的PHP json_encode如果有多个返回数组,但如果是单个则返回对象?
【发布时间】:2014-04-03 14:19:10
【问题描述】:

我有一个 Windows 桌面小工具,几个月前我的少数用户突然停止工作。似乎是他们突然不喜欢跨域请求了(尽管这里所有的服务器都在我们的内网上)。所以,我正在重写这个东西,以便它转到一个我有很多控制权的单一后端服务器......并且它对后端的 Ajax 查询设置为使用数据类型:jsonp。同时,gadget查询la Ajax的php脚本调用SOAP服务,取回数据,转为数组,然后使用json_encode转为字符串,并在Gadget上添加一个回调函数的引用/ javascript 方面。

我的问题似乎与 json_encode 有关。如果 SOAP 响应包含单个数据记录,它将作为对象发送。如果 SOAP 响应包含多条记录,它会在其周围加上括号,就像一个数组一样。

例子:

单条记录:

`{
  "SmeDetail": {
    "SipAddress": "jane.smith@whatever.com",
    "SubjectExpert": "Smith,Jane",
    "SubjectMatter": "Unix"
  }
}`

多条记录:

`{
  "SmeDetail": [
    {
      "SipAddress": "fred.flintstone@whatever.com",
      "SubjectExpert": "Flintstone,Fred",
      "SubjectMatter": "Bedrock"
    },
    {
      "SipAddress": "barney.rubble@whatever.com",
      "SubjectExpert": "Rubble,Barney",
      "SubjectMatter": "Bedrock"
    },
    {
      "SipAddress": "wilma.flintstone@whatever.com",
      "SubjectExpert": "Flintsone,Wilma",
      "SubjectMatter": "Bedrock"
    }
  ]
}`

在 php 脚本中,典型的 SOAP 调用如下所示:

$Service_URL = 'http://server/PROD/OurWcfService/WcfService.svc?wsdl';
$client = new SoapClient($Service_URL);
$res= $client->GetSMEDetails($params)->GetSMEDetailsResult;

然后将 $res 输入到这个例程中:

$json_data = json_encode((array)$res);
echo $_GET['callback_name'].'('.$json_data.');';

这个回声是作为 Ajax 响应反馈的。

我不确定我什至在哪里读到使用这个 json_encode((array)$res) 将 Soap 响应转换为数组,然后是 json 编码字符串。但我想知道我是否在这里做错了什么?我想我需要确保将单个记录作为数组推送。而且我宁愿以“正确的方式”来解决这个问题,而不是对字符串进行某种破解。

有什么想法吗?

【问题讨论】:

    标签: php arrays soap json


    【解决方案1】:

    我认为问题的发生是因为 GetSMEDetailsResult 返回的不是数组(单记录)而是单记录本身。

    检查“SmeDetail 是否具有关联性”怎么样?

    提示:How to check if PHP array is associative or sequential?

    function isAssoc($arr)
    {
        return array_keys($arr) !== range(0, count($arr) - 1);
    }
    
    if(isAssoc($res['SmeDetail'])) $res['SmeDetail'] = array($res['SmeDetail']);
    

    这个解决方案很丑陋,但它应该可以工作。 另一种方法是检查“是否设置了 SipAddress”:

    if(isset($res['SmeDetail']['SipAddress'])) $res['SmeDetail'] = array($res['SmeDetail']);
    

    【讨论】:

    • 对于未来的读者:我在 PHP 脚本中进行了一些调试,发现......确实......原始 $res 值是一个 stdClass 对象“SmeDetail”,包含一个 stdClass 对象,由各种字段...当 $res 返回单个“记录”时。然而,当 $res 返回多条记录时,它返回了一个 stdClass 对象“SmeDetail”,其中包含一个由 stdClass 对象组成的数组,每条记录一个。这样看来,SOAP 客户端将 XML 处理成一个问题所在的对象。
    • 顺便说一下,我的 PHP 版本是 5.4.14。
    猜你喜欢
    • 1970-01-01
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 2018-06-29
    • 1970-01-01
    相关资源
    最近更新 更多