2013-09-26 28 views
1

我想通过一些JSON数据循环并提取特定值。这里是JSON数据和部分工作代码。PHP JSON对象嵌套循环数据语法

$jsondata = ' 
[ 
    { 
    "id" : "421356", 
    "trip_update" : { 
    "trip" : { 
     "trip_id" : "421356", 
     "start_time" : "12:05:00", 
     "start_date" : "20130926", 
     "route_id" : "15" 
    }, 
    "stop_time_update" : { 
     "stop_sequence" :70, 
     "departure" : { 
     "delay" : 240, 
     "time" : 1380215057 
     }, 
     "stop_id" : "6090" 
    }, 
    "stop_time_update" : { 
     "stop_sequence" :71, 
     "departure" : { 
     "delay" : 240, 
     "time" : 1380215075 
     }, 
     "stop_id" : "6095" 
    } 
    } 
}]'; 
$result = json_decode($jsondata); 

foreach($result as $value) { 
    echo "trip_id: ".$value->trip_update->trip->trip_id; 
    if (gettype($value->trip_update) == "object") { 
    foreach($value->trip_update as $item) { 
     echo " - stop_sequence: ".$item->stop_sequence; 
    } 
    } 
} 

我可以在'trip_update-> trip'下得到第一级的数据。但'trip_update'中也可以有任意数量的'stop_time_update'数据。由于这些数据与trip_update数据有关,因此我需要遍历它并关联它。

的最终目标是将这些数据保存到数据库(在代码中未示出),所以为了清楚起见,这将是简化2行DB数据的我想在这个例子中,以节省:

trip_id,stop_sequence 
421356,70 
421356,71 

源数据中可以有任意数量的stop_sequences。

这是一个互动的链接代码,编辑或乱用: http://sandbox.onlinephpfunctions.com/code/f21ca8928da7de3e9fb351edb075d0a446906937

+1

尝试[JSONlint](http://jsonlint.org),虽然这是有效的JSON,的'stop_time_update'被移除(或者更确切地说,第一,如果改写第二个)第二次出现,则对象属性和能不定义两次。它应该是一个包含两个对象的数组 –

+0

谢谢,它验证。 –

+0

我知道它验证,因为我在我的评论中提到它。要点是,它的结构很糟糕,你应该把它提到这个JSON的提供者。 –

回答

1

嗨,也许你可以更改名称。

function next_update($coincidencias){ 
$replace=$coincidencias[0].$GLOBALS["json_stop_time_update"]++; 
return $replace; 
} 
$result= preg_replace_callback("/stop_time_update/","next_update",$jsondata); 
$result = json_decode($result); 
+0

有用的圣牛。我能够重命名所有这些,然后遍历它们并从新对象中提取数据。尼斯。这绝对是一个解决方案 - 修复糟糕的JSON数据。在标记之前,让我看看其他人。 –

1

你应该返工你的JSON - 你有多个同名的键,尝试做print_r($result),看我是什么谈论 - PHP会一次性覆盖“stop_time_update”键,您将只能访问最后一个条目。相反,你应该组织你的JSON这样的:

[ 
    { 
    "id" : "421356", 
    "trip_update" : { 
    "trip" : { 
     "trip_id" : "421356", 
     "start_time" : "12:05:00", 
     "start_date" : "20130926", 
     "route_id" : "15" 
    }, 
    "stop_time_update" : [{ 
     "stop_sequence" :70, 
     "departure" : { 
     "delay" : 240, 
     "time" : 1380215057 
     }, 
     "stop_id" : "6090" 
    }, { 
     "stop_sequence" :71, 
     "departure" : { 
     "delay" : 240, 
     "time" : 1380215075 
     }, 
     "stop_id" : "6095" 
    }] 
    } 
}] 

,那么你就可以通过你的数据迭代这样的:

foreach($result[0]->trip_update->stop_time_update as $update) 
{ 
    $time = $update->departure->time; 
    ... 
} 

如果你不能改变的数据结构,那么什么也许可以帮助你是一个PULL解析器 - 一个不返回分析数据结构,但允许你使用数据流的方式 - 这样你可以遍历每个节点。我设法找到了唯一的一个是扩展PHP:

https://github.com/shevron/ext-jsonreader

检查用法部分。

+0

谢谢,但我无法控制JSON。它来自外部来源。我想我可以做一些正则表达式替换,以相同的trip_update另一种方式更改stop_time_update的第一个实例和后续的一个。这似乎可能不起作用,但如果你能举出一个例子,我可以用真实文件来尝试。我希望能有另一种方式。 –

+0

虽然我确实看到了你的观点。 print_r($ result)显示只有最后一个stop_time_update数据保存在对象中。 –

+1

这正是我的观点 - 如果你的JSON包含重复键,你将只能访问最后提供的值;我不知道一个JSON解析方法,将不同处理 – adamziel

1

JSON响应无效,因为它包含重复密钥,但JSON不是allow duplicate keys

您应该联系您尝试请求此回复的服务。

如果你有一个有效的JSON响应,那么你可以使用json_decode函数解码它,该函数返回一个对象或数组(取决于第二个参数);

对此,您不能使用JSON parser,因为它会因相同的密钥而覆盖第一个元素。唯一适当的解决方案是询问谁创建了“JSON”来修复他的代码,以使用具有唯一键的数组或对象。

另一种方法是编写自己的解码功能,用于解析它

+0

感谢您的回答。编写解析可以工作,或使用现有解析。由于这是一个技术演示,我已经使用Erick的解决方案,因为它的实施更快。 –

2

,如果你写你自己的解析器或使用流解析器与回调你可能会得到更好的结果。这是一个使用回调函数的解析器的PHP implementation。因此,无论将整个JSON数据读入内存,解析器都会以块读取数据,并在新对象启动或读取属性时通知您的“侦听器类”。通过这样做,您应该为每个stop_time_update属性获取单独的回调事件,而不仅仅是解析数组中的一个值。

SAX用于XML非常相似。

+0

嘿,这是一个非常有用的解析器。我认为它会起作用,也许我会在稍后使用它。但是现在Erick的解决方案起作用了。 –