3

I am using Curl to perform a GET request on a Sage server. The response is in JSON format, but I am unable to access the key/values.

An example of the response is below:

{
"$descriptor": "Sage Accounts 50 | tradingAccount.",
  "$totalResults": 1508,
  "$startIndex": 1,
  "$itemsPerPage": 1508,
  "$resources": [
   {
      "$url": "http://it1:5493/sdata/accounts50/GCRM/{53C58AA8-1677-46CE-BCBE-4F07FED3668F}/tradingAccountCustomer(9a7a0179-85cb-4b65-9d02-73387073ac83)?format=atomentry",
      "$uuid": "9a7a0179-85cb-4b65-9d02-73387073ac83",
      "$httpStatus": "OK",
      "$descriptor": "",
      "active": true,
      "customerSupplierFlag": "Customer",
      "companyPersonFlag": "Company",
      "invoiceTradingAccount": null,
      "openedDate": "\/Date(1246834800000+0100)\/",
      "reference": "1STCL001",
      "reference2": null,
      "status": "Open"
    }
    /* Additional results omitted for simplicity */
}

I need to access 2 key/value pairs for each child of $resources. The first is $uuid and the second is reference.

I have attempted various methods including:

$result=curl_exec($ch);
$resources = $result->{'$resources'};
print_r($resources); /* Non-object error */

Can someone shed some light on how I can access these key/values, please?

Update

If I perform the following action, I receive a Notice: Trying to get property of non-object error.

$result = json_decode(curl_exec($ch));
$resources = $result->{'$resources'};
print_r($resources);

Edit 2

Entire code currently used:

<?php 
header('content-type:application/json');
error_reporting(E_ALL);

$url = "http://it1:5493/sdata/accounts50/GCRM/-/tradingAccounts?format=json";

$header = array();
$header[] = 'Authorization: Basic bWFuYWdlcjpjYmwyMDA4';
$header[] = 'Content-Type: application/json;';

//  Initiate curl
$ch = curl_init();
// Will return the response, if false it print the response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Set the url
curl_setopt($ch, CURLOPT_URL,$url);
// Set the header
curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
// Execute
$result = json_decode(curl_exec($ch));

if ($result === false)
{
    // throw new Exception('Curl error: ' . curl_error($crl));
    print_r('Curl error: ' . curl_error($ch));
}
// Closing
curl_close($ch);

// Access property $resources
$resources = $result->{'$resources'};

// Dump results
print_r($resources);


?>

Edit 3

Output of var_dump($result);

string '{
   "$descriptor": "Sage Accounts 50 | tradingAccount",
   "$totalResults": 1508,
   "$startIndex": 1,
   "$itemsPerPage": 1508,
   "$resources": [
      {
       "$url": "http://it1:5493/sdata/accounts50/GCRM/{53C58AA8-1677-46CE-BCBE-4F07FED3668F}/tradingAccountCustomer(9a7a0179-85cb-4b65-9d02-73387073ac83)?format=atomentry",
       "$uuid": "9a7a0179-85cb-4b65-9d02-73387073ac83",
       "$httpStatus": "OK",
       "$descriptor": "",
       '... (length=5333303)
Community
  • 1
  • 1
MikeF
  • 485
  • 6
  • 22

6 Answers6

2

The server is returning the JSON encoded as UTF-8 with BOM which puts 3 characters at the begining of the string. Just try to obtain the JSON correctly encoded or if you can't, remove the 3 first characters and then use json_decode to obtain the PHP object.

Peter
  • 447
  • 2
  • 10
  • 1
    Thanks Peter. After further investigation it was found that the Sage server was indeed returning with UTF-8 with BOM encoding. A quick `substr($result,3)` resolved this issue. – MikeF Aug 21 '15 at 14:07
1

UPDATE:
The server response was UTF-8 encoded with BOM (byte-order-mark) which caused the json_encode to fail with JSON_ERROR_SYNTAX

working code

$string = curl_exec($ch);

$object = json_decode(remove_utf8_bom($string),true);


foreach ($object as $key => $value)
    if (is_array($value))
        foreach($value as $k=>$arr){
            print $arr['$uuid'] . PHP_EOL;
            print $arr['reference'] . PHP_EOL;
        }

function remove_utf8_bom($text)
{
    $bom = pack('H*','EFBBBF');
    $text = preg_replace("/^$bom/", '', $text);
    return $text;
}

remove_utf8_bom function ripped from here https://stackoverflow.com/a/15423899/5043552


This is how you can access the key/values, assuming $result is the contents of json_decode as per your latest edit.

foreach ($result->{'$resources'} as $obj){
    print $obj->{'$uuid'} . PHP_EOL;
    print $obj->reference . PHP_EOL;
}
// prints out
// 9a7a0179-85cb-4b65-9d02-73387073ac83
// 1STCL001
Community
  • 1
  • 1
Alex Andrei
  • 7,315
  • 3
  • 28
  • 42
0

You're missing json_decode call. Try this:

$result = json_decode(curl_exec($ch));
$resources = $result->{'$resources'};
Nenad Mitic
  • 577
  • 4
  • 12
  • This returns the following error: `Notice: Trying to get property of non-object in C:\wamp\www\sage-test.php on line 32`. Which relates to `$resources = $result->{'$resources'};` – MikeF Aug 21 '15 at 12:13
  • Double check what you're getting from the remote server. Just echo whatever curl_exec is returning. – Nenad Mitic Aug 21 '15 at 12:40
0
$result = json_decode(curl_exec($ch)); // Decode the JSON
$resources = $result->{'$resources'}; // Access the $resources property which is an array
print_r($resources); // Prints an array
Peter
  • 447
  • 2
  • 10
0
$result = json_decode(curl_exec($ch));
$resources = $result->{'$resources'};

You have to decode JSON

pguetschow
  • 5,176
  • 6
  • 32
  • 45
0

The key fact here that everyone else seems to be missing is that $resources is an defined in the JSON as array, not an object, so json_decode() will turn it into a PHP array, not a PHP object.

$result = json_decode(curl_exec($ch));
$resources = $result['$resources'];   //resources is an array, not an object.

foreach ($resources as $resource) {
    //but each resource is an object...
    print $resource->{'$url}."\n";
    print $resource->{'$uuid}."\n";
    // ...etc...
}
Simba
  • 4,952
  • 3
  • 19
  • 29
  • I am now receiving a `Warning: Invalid argument supplied for foreach() ` error – MikeF Aug 21 '15 at 12:25
  • Add a `var_dump` or `print_r` before the `foreach()` to see what's going on. – Simba Aug 21 '15 at 12:28
  • On the bright side, at least the code got past the `$resource = $result['$resources']` line, so that much seems to have worked. And that was the main point of my answer. – Simba Aug 21 '15 at 12:28