-3
$ONEANSWER = '{
  "name": "Attendee terms and conditions",
  "id": "1z6wzmd95",
  "numberofcolumns": "1",
  "type": "check-box",
  "answers": {
    "answer": {
      "@attributes": {
        "code": "1z6x061vg",
        "revision": "8969663434"
      },
      "name": "Attendee terms and conditions",
      "sort": "0",
      "type": "label"
    }
  }
}';

$THREEANSWERS ='{
  "name": "GPP What printing are you responsible for (please select all that apply)?",
  "id": "1ygc0dvbi",
  "numberofcolumns": "2",
  "type": "check-box",
  "answers": {
    "answer": [
      {
        "@attributes": {
          "code": "1yx7dx07w",
          "revision": "8986379556"
        },
        "name": "Advertising - posters / signage",
        "sort": "0",
        "type": "label"
      },
      {
        "@attributes": {
          "code": "1ygc0eaqt",
          "revision": "8986379550"
        },
        "name": "Books and photo books",
        "sort": "1",
        "type": "label"
      },
      {
        "@attributes": {
          "code": "1yx7dx07y",
          "revision": "8986379557"
        },
        "name": "Décor",
        "sort": "2",
        "type": "label"
      }
    ]
  }
}';


$ONEANSWER =json_decode($ONEANSWER, true);
$THREEANSWERS  =json_decode($THREEANSWERS , true );

echo count($ONEANSWER['answers']);  //expect 1 get 1
echo count($ONEANSWER['answers']['answer']);  //expect 1 get 4

echo count($THREEANSWERS ['answers']); //expect 1 get 1
echo count($THREEANSWERS ['answers']['answer']); //expect 3 get 3

Running the above returns 4 but I am expecting 1. There is 1 'array->answers->answer' node so how come I get 4?

I have exactly the same JSON format with multiple 'answers' and the same approach is returning the right amount. Just seems to fail when there is one answer?

Thanks

megaSteve4
  • 1,760
  • 1
  • 17
  • 24
  • 3
    `$oneAnswer['answers']['answer']` has __4__ elements: `@attributes`, `name`, `sort`, `type`. Why do you expect 1 - is a mystery. – u_mulder Jul 08 '22 at 10:57
  • 1
    _"so how come I get 4?"_ - because what you actually wanted, was to count how many items `$oneAnswer['answers']` contains ... – CBroe Jul 08 '22 at 11:03
  • You should cast object as array, then you get your desired result. – Lessmore Jul 08 '22 at 11:03
  • `There is 1 'array->answers->answer' node so how come I get 4?`...you're asking it to count how many items are _within_ that node. Since its an object (or technically an associative array if thats how you decoded it) rather than an array, it will count the number of properties. Obviously there will only ever be one node called "answer" because you can't use a node name twice in the same object- so that's not a question you need to ask – ADyson Jul 08 '22 at 11:06
  • `I have exactly the same JSON format with multiple 'answers'`...unlikely, since, as i just mentioned you cannot use a node name twice. Probably its actually an array and you haven't noticed the difference in this version. Show us an example of what you mean, if you're unsure. – ADyson Jul 08 '22 at 11:07
  • @u_mulder but then why does my second example with more elements only return 3 – megaSteve4 Jul 08 '22 at 11:21
  • @CBroe but that returns 1 even under the example with 3 'answers' – megaSteve4 Jul 08 '22 at 11:22
  • @ADyson my terminology might be off but I have added a second example with multiple answers - (taken from a 3rd party production system? – megaSteve4 Jul 08 '22 at 11:23
  • Yeah that returns an array instead of a single object (as clearly shown by the `[` and `]` at either end of the list of answers). So in that case your code would count the number of entries in the array. – ADyson Jul 08 '22 at 11:25
  • 2
    There was no example with three answers before, and _based on what_ you wanted to get the result you said you needed, was also not clearly specified. And now with your three answers example, even the structure appears to be different - answers-answer is an array now, whereas before it was an object. – CBroe Jul 08 '22 at 11:26
  • Is there any way to get the source system amended so it always generates an array for that property, even when there's only one entry? As you're discovering it's a real pain when systems return inconsistent data formats, the makers obviously didn't put much thought into how people might actually use it – ADyson Jul 08 '22 at 11:27
  • 1
    @megaSteve4 in you first example you have a `{` witch will be transpated as an associative array , in the secont one you have a `[` witch will be transpated as sequential array. So different formats? Why? Where is that json coming from? The problem is there – angel.bonev Jul 08 '22 at 11:33
  • @adyson ok understood thank you. the 3rd party system is beyond my control. ok now I understand the different results are if there are more than one result or not. have go it to work by forcing my result to an array echo count(array($ONEANSWER['answers']['answer'])); //expect 1 get 1 – megaSteve4 Jul 08 '22 at 11:36

2 Answers2

1

OK just for reference so as per multiple comments the 'answer' node is formatted differently in the response JSON if there are more than one 'answers' note the square brackets on the multiple answer example.

Setting the one answer to an array got it to work

echo count(array($ONEANSWER['answers']['answer'])); //expect 1 get 1

in production I can just check if it is an array and if not make it one.

megaSteve4
  • 1,760
  • 1
  • 17
  • 24
1

If it's associative array make it sequential array

function isAssoc($array) {
    $array = array_keys($array);
    return ($array !== array_keys($array));
}

if (isAssoc($ONEANSWER['answers']['answer'])) {
    $ONEANSWER['answers']['answer'] = [$ONEANSWER['answers']['answer']];
}
if (isAssoc($THREEANSWERS['answers']['answer'])) {//it's not associative array
    $THREEANSWERS['answers']['answer'] = [$THREEANSWERS['answers']['answer']];
}

using isAssoc

angel.bonev
  • 2,154
  • 3
  • 20
  • 30
  • @megaSteve4 I realy hate when 3th party systems return results like that. In one perfect universe this operation won't be necessary. The community sometime is too harsh. Glad to help. Cheers – angel.bonev Jul 11 '22 at 13:41