1

I'm struggling with parsing a web service response JSON in cases where the service returns an error.

Example JSON - success flow:

{
    "Response": [{
        "iconPath" : "/img/theme/destiny/icons/icon_psn.png",
        "membershipType": 2, 
        "membershipId": "4611686018429261138",    
        "displayName": "Spuff_Monkey"
     }],
    "ErrorCode": 1,
    "ThrottleSeconds": 0,
    "ErrorStatus": "Success",
    "Message": "Ok",
    "MessageData":{}
}

Example JSON - error flow:

{
    "ErrorCode": 7,
    "ThrottleSeconds": 0,
    "ErrorStatus": "ParameterParseFailure",
    "Message": "Unable to parse your parameters.  Please correct them, and try again.",
    "MessageData": {}
}

Now my PHP:

function hitWebservice($endpoint) {

    $curl = curl_init($endpoint);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));

    $json_response = curl_exec($curl);

    if(curl_exec($curl) === false) {
        echo "Curl error: " . curl_error($curl);
    }

    curl_close($curl);

    $array_response = json_decode($json_response, true);
    $function_response = array();

    if (!isset($array_response['Response'])) {
        $function_response = $array_response;
    } else {
        $function_response = $array_response['Response'];
    }

    return $function_response;
}

What I'm trying to achieve is when the JSON includes the "Response" block I put that in a new array and return only that detail from the function, where "Response" isn't present I want to return the full JSON as an array.

However at present, where there is no "Response" I get an empty array.

There's something wrong with my logic and I can't get past it in my tiny mind, so it's time to reach out for help!

Sumurai8
  • 20,333
  • 11
  • 66
  • 100
  • 1
    This should work fine as you have it. http://3v4l.org/p7QiY Please post the surrounding code -- most importantly, the `function` definition from which you return `$function_response`. – Michael Berkowski Aug 16 '15 at 14:16
  • I can't reproduce this error. – Sumurai8 Aug 16 '15 at 14:20
  • Original post updated to include full function – Luke Wallwin Aug 16 '15 at 14:21
  • @MichaelBerkowski With a reputation like yours you should really know better than creating answers OFF SITE where they are likely to dissapear well before the question does. – RiggsFolly Aug 16 '15 at 14:24
  • @RiggsFolly That is _not_ an answer of any kind. It is a validation that the current code worked. The entire comment is likely to disappear later. – Michael Berkowski Aug 16 '15 at 14:25
  • @RiggsFolly And it was posted as a request to the OP to improve what had been posted. I'm here to improve questions. Read the edit history and you'll see what I mean. – Michael Berkowski Aug 16 '15 at 14:26
  • 1
    Can you confirm that the 'error flow' JSON is actually what you think it is? Perhaps the response from `$endpoint` contains an empty array (array of zero objects) for the `Response` part. That would explain your empty array. Note: I find it suspicious that `Response` is actually an array of objects in the 'success flow', instead of just an object! – Marten Koetsier Aug 16 '15 at 14:36
  • @RiggsFolly How do you read the edit history? – CodeGodie Aug 16 '15 at 14:43
  • @CodeGodie Click on the `edited 20 minutes ago` link about the editors icon and name – RiggsFolly Aug 16 '15 at 14:45
  • @MartenKoetsier - you hit the nail on the head! It's not actually an array and so when I handle it as an object it behaves as I require – Luke Wallwin Aug 16 '15 at 14:59

3 Answers3

1

If you notice, both a good and a bad response contain an ErrorCode

You would be better designing your code to work from this field rather than test a field that may or may not exist.

So try this instead :-

$array_response = json_decode($json_response, true);

switch ( $array_response['ErrorCode'] ) {
case 1 :
    do_errorCode_1_processing($array_response)
    break;
 case 2 :
    do_errorCode_2_processing($array_response)
    break;

 // etc etc


}
RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
  • Thanks! I'll work logic like this in. The problem turned out to be the endpoint response not being an array, once I treated it as a object everything was fine – Luke Wallwin Aug 16 '15 at 15:00
1

Judging from the fact that Response is an array of objects in the JSON, I suspect that the error-flow response may also contain a Response-field, but with an empty array as value ([]). That would explain your current result.

Therefore, do not check for the existence of Response. It may just be an empty array. Instead, check for the ErrorCode, ErrorStatus or ErrorMessage (whichever you think is most suitable). For example:

if ($array_response['ErrorStatus'] != "Success") {
    $function_response = $array_response;
} else {
    if (!isset($array_response['Response'])) {
        $function_response = null;
    } else {
        $function_response = $array_response['Response'];
    }
}

In the Success-case, you want to check for existence of Response, so that if it does not exist (but it is expected), you can raise some error).

Another possible solution is to count the number of responses:

if (!isset($array_response['Response'])) {
    $function_response = $array_response;
} else {
    if (count($array_response['Response']) > 0) {
        $function_response = $array_response['Response'];
    } else {
        $function_response = $array_response;
    }
}
Marten Koetsier
  • 3,389
  • 2
  • 25
  • 36
-1

isset () is not the right function for checking if the key in an array is present or not.

Use array_key_exists () instead.

http://php.net/manual/en/function.array-key-exists.php

so your code should look like this:

$array_response = json_decode($json_response, true);

$function_response = array();
if (array_key_exists('Response', $array_response)) {
    $function_response = $array_response['Response'];
} else {
    $function_response = $array_response;
}

return $function_response;

The above should do the trick.

Dr. Ehsan Ali
  • 4,735
  • 4
  • 23
  • 37
  • It's not exactly that, `array_key_exists` is like `isset` but won't check whether the value is null. http://stackoverflow.com/q/20116275/3132718 – Al.G. Aug 16 '15 at 14:27
  • If so then I can't see any error in his code, probably he is doing some mistake somewhere else. OP should post more of his code. The problem lies somewhere else. – Dr. Ehsan Ali Aug 16 '15 at 14:29