【问题标题】:php foreach not working properly on json object [duplicate]php foreach 在 json 对象上无法正常工作 [重复]
【发布时间】:2015-02-02 23:14:48
【问题描述】:

这个帖子讨论是这样还是那样做。事实是没有另一个是不够的。可以在此处找到解决方案(以及对问题的更清晰描述):

how to iterate over JSON property not knowing if it's array or not?


我将以下 JSON 解析为对象 (stdClass):

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

在 XML 中也是如此,更具可读性,但无法在我的 var_dump 中漂亮地打印出这么好的 JSON...

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

我用这段代码遍历它...

        $r=array();
        $i=0;

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

            $r[$i]["depTime"] = $m->departure->datetime; //tid för avgången
            $segmentid = get_object_vars($m->segmentid->mot);
            $r[$i]["typText"] = $segmentid['#text'];
            //$r[$i]["typ"] = $segmentid['@displaytype'];
            $r[$i]["nr"] = $m->segmentid->carrier->number;
            $r[$i]["destination"] = $m->direction; //slutstation (som står på bussen, tåget etc.)
            $r[$i]["operator"] = $m->segmentid->carrier->name;

            $i++;

        }

...它运行良好,直到我得到这样的响应,其中只有一个 DEPARTURE 元素,在这种情况下,我会抛出这个错误:

(http500) Notice: Undefined property: stdClass::$departure

所以在我看来,循环尝试第二次运行,在第一行失败

$r[$i]["depTime"] = $m->departure->datetime; //tid för avgången

因为 $m->departure 不存在。但那为什么 $m 会自己存在呢?

----- 更新 -------

这是当 DEPARTURESEGMENT 中有多个项目时 JSON 的样子:

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

在这种情况下,我的循环工作正常。但是,当只有一个项目时,我需要一个像 @chiliNUTS 这样描述的循环,在 foreach 条件下更浅一层。

有没有办法编写一个循环,如果它是一个数组,它将遍历 DEPARTURESEGMENT 中的一个对象数组,如果不是,则只从第一个对象中提取值?我是否必须在循环之前放置一个单独的 if 子句来测试是否真的需要循环(从而在循环内和循环外加倍获取我想要的值的逻辑)?

【问题讨论】:

  • But why then would $m even exist itself? 它将遍历对象的属性。看看pastebin.com/pUv2eAgK你就明白了。
  • 是的,但它应该通过 DEPARTURESEGMENTs 对吗?而且只有其中之一。
  • 循环会经过departuredirection等等。所以,$m 里面不会有departure,因为在第一个循环中它已经是departure
  • 如果离开段总是settet $m默认是一个空的stdclass,如果你把项目放在上面它会变成一个数组如果有多个元素,如果不,它是一个标准类 - 因为你的错误表明离开元素不存在,是什么持有整个 $apiData-&gt;getdeparturesresult-&gt;departuresegment 元素? - 无论如何,如果您的元素是标准类,您可以在 foreach 循环之前检查,否则设置 $apiData-&gt;getdeparturesresult-&gt;departuresegment = array($apiData-&gt;getdeparturesresult-&gt;departuresegment)

标签: php json parsing loops stdclass


【解决方案1】:

$m departure。您正在循环遍历departuresegment 的每个元素。所以首先$mdeparture 然后是direction,然后是segmentid。你可能只是想要

foreach ($apiData-&gt;getdeparturesresult-&gt;departuresegment as $m)

测试

$json = '{"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"}}}}}';
$apiData = json_decode($json);
foreach ($apiData->getdeparturesresult->departuresegment as $key => $m) {
    echo "key:" . $key . "\r\n";
    echo '$m:' . print_r($m, true);
    echo "\r\n";
}

输出

key:departure
$m:stdClass Object
(
    [location] => stdClass Object
        (
            [@id] => 7461018
            [@x] => 12.523958
            [@y] => 57.938402
            [name] => Noltorps centrum
        )

    [datetime] => 2014-12-04 23:05
)

key:direction
$m:Alingsås station
key:segmentid
$m:stdClass Object
(
    [mot] => stdClass Object
        (
            [@displaytype] => B
            [@type] => BLT
            [#text] => Buss
        )

    [carrier] => stdClass Object
        (
            [name] => Västtrafik
            [url] => http://www.vasttrafik.se/
            [id] => 279
            [number] => 1
        )

)

只有第一个有日期时间...

【讨论】:

  • 不,这不是问题,它适用于答案中的多个元素。我不在所有子元素中寻找 depTime,我只从离开元素中选择 depTime(参见循环中的代码)。我不是在迭代 DEPARTURE 元素/属性,而是在迭代它的父 DEPARTURESEGMENT
  • @MattiasSvensson:你的意思是当你只有一次出发时,你的json看起来像这样:{"getdeparturesresult":{"departure": ...}}?
  • 查看编辑,看起来您的循环没有按照您的预期进行
  • 不,如果 $m 本来是 DEPARTURE,那么它会在循环内的第一行每次都失败,因为 $m 是 DEPARTURE 永远不会有一个名为 DEPARTURE 的子属性。就像我说的,只要有 1 个以上的离开段元素,它就可以正常工作。
  • @anhlc 没有,结构还是一样的,只有一个DEPARTURESEGMENT(department、direction和segmentid的父级)时出现问题。
猜你喜欢
  • 2020-11-17
  • 2015-02-13
  • 2014-03-18
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
相关资源
最近更新 更多