как перебирать свойство JSON, не зная, массив или нет?

У меня есть эта проблема, когда API отвечает мне, когда DEPARTURESEGMENT иногда содержит только один объект и иногда содержит массив объектов. В зависимости от того, в каком случае это, мне кажется, нужны разные логики в моей петле foreach.

Ответ A:

{ "getdeparturesresult":{ "departuresegment":[{ "departure":{ "location":{ "@id":"7461018", "@x":"12.523958", "@y":"57.938402", "name":"Noltorps centrum" }, "datetime":"2014-12-04 23:05" }, "direction":"Alingsås station", "segmentid":{ "mot":{ "@displaytype":"B", "@type":"BLT", "#text":"Buss" }, "carrier":{ "name":"Västtrafik", "url":"http://www.vasttrafik.se/", "id":"279", "number":"1" } } }, { "departure":{ "location":{ "@id":"7461018", "@x":"12.523958", "@y":"57.938402", "name":"Noltorps centrum" }, "datetime":"2014-12-04 23:05" }, "direction":"Alingsås station", "segmentid":{ "mot":{ "@displaytype":"B", "@type":"BLT", "#text":"Buss" }, "carrier":{ "name":"Västtrafik", "url":"http://www.vasttrafik.se/", "id":"279", "number":"1" } } } ] } } 

Работает с этим циклом:

 foreach ($apiData->getdeparturesresult->departuresegment as $m) { 

Хотя этот ответ B:

 { "getdeparturesresult":{ "departuresegment":{ "departure":{ "location":{ "@id":"7461018", "@x":"12.523958", "@y":"57.938402", "name":"Noltorps centrum" }, "datetime":"2014-12-04 23:05" }, "direction":"Alingsås station", "segmentid":{ "mot":{ "@displaytype":"B", "@type":"BLT", "#text":"Buss" }, "carrier":{ "name":"Västtrafik", "url":"http://www.vasttrafik.se/", "id":"279", "number":"1" } } } } } 

нужен такой цикл (иначе он выдает ошибку):

 foreach ($apiData->getdeparturesresult as $m) { 

Есть ли способ написать цикл безотказным для того, является ли DEPARTURESEGMENT массивом объектов или только одним объектом (скобки [] – это единственное отличие от структуры json?) Или мне нужно как-то проверить и сначала увидеть, DEPARTURESEGMENT – массив или нет, и отправка в два разных цикла в зависимости от результата?

У вас есть несколько способов, которые могут вам помочь:

  • is_array
  • is_object
  • instanceof // если вы получаете определенный объект
  • GetType
  • json_decode второй параметр, который, если установлен в true, пытается декодировать json как массив

В вашей ситуации вы, вероятно, будете в порядке, выполнив следующее:

 if (is_object($entry)) { handleObject($entry); } elseif (is_array($entry) && count($entry)) { foreach ($entry as $e) { handleObject($e); } } 

У меня есть эта небольшая полезная функция в моем стандартном репертуаре:

 function iter($x) { if(is_array($x)) return $x; if(is_object($x)) { if($x instanceof \Iterator) return $x; if(method_exists($x, 'getIterator')) return $x->getIterator(); return get_object_vars($x); } return array($x); } 

Таким образом, вы можете использовать любую переменную с foreach без предварительной проверки:

  foreach(iter($whatever) as $item) ... 

Как насчет проверки того, массив или нет с is_array ? Я сделал простой пример его использования здесь – http://codepad.org/WNjbIPZF