0

I have a Windows Desktop Gadget that, for a small number of my users, suddenly stopped working a few months back. Seemed to be that they suddenly didn't like cross-domain requests (even though all servers are on our intranet here). So, I'm rewriting the thing so that it goes to a single backend server that I have a lot of control over... and its Ajax queries to the backend are set to use data Type: jsonp. Meanwhile, the php script that the gadget queries a la Ajax calls a SOAP service, gets the data back, turns it into an array, and then uses json_encode to turn it into a string and add a reference to a callback function on the Gadget / javascript side.

My problem seems to be with json_encode. If the SOAP response includes a single data record, it sends it as an object. If the SOAP response contains multiple records, it's slapping brackets around it, like an array.

Examples:

Single record:

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

Multiple records:

`{
  "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"
    }
  ]
}`

In the php script, a typical SOAP call goes like this:

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

and then $res is fed to this routine:

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

And that echo is what's fed back as the Ajax response.

I'm not sure where I even read about using this json_encode((array)$res) to do the conversion from the Soap response into an array, then the json encoded string. But I'm wondering if I'm doing something wrong here? I guess I need to make sure that single records are pushed through as an array. And I'd rather fix that the "right way" rather than do some sort of hack on the string.

Any thoughts?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
DaveyBoy
  • 435
  • 4
  • 20

1 Answers1

0

I think the problem occurs cause GetSMEDetailsResult returns not array(singlerecord) but singlerecord itself.

What about checking "is SmeDetail associative"?

hint: 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']);

This solution is ugly but it should work. Another way is to check "is SipAddress set":

if(isset($res['SmeDetail']['SipAddress'])) $res['SmeDetail'] = array($res['SmeDetail']);
Community
  • 1
  • 1
Eropi4
  • 61
  • 2
  • For future readers: I put in some debugging into the PHP script and found... indeed... the raw $res value was a stdClass Object "SmeDetail", containing a stdClass Object consisting of the various fields... when $res was returning a single "record". However, when $res returned multiple records, it returned a stdClass Object "SmeDetail" that contained an ARRAY of stdClass Objects, one for each record. So it would appear that the SOAP client processing of the XML into an object where the problem lay. – DaveyBoy Apr 04 '14 at 13:29
  • My PHP version is 5.4.14, by the way. – DaveyBoy Apr 04 '14 at 13:32