我正在从mongodb数据库中读取文档并将其通过php传递给客户端。
该文档包含数组属性。问题是客户端将其作为具有名称0
,1
等属性的对象接收,而不是标准数组。
这是原始数据:
{
"_id" : ObjectId("573b47a1f99a8a1f9a6278a5"),
"persons" : [
{
"name" : "Moshe",
},
{
"name" : "E",
}, ...
]
}
根据要求,我附加了var_export:
array (
0 =>
MongoDB\Model\BSONDocument::__set_state(array(
'_id' =>
MongoDB\BSON\ObjectID::__set_state(array(
)),
'persons' =>
MongoDB\Model\BSONArray::__set_state(array(
0 =>
MongoDB\Model\BSONDocument::__set_state(array(
'name' => 'Moshe',
)),
1 =>
MongoDB\Model\BSONDocument::__set_state(array(
'name' => 'E',
)),
)),
)),
)
和var_dump:
array(1) {
[0]=>
object(MongoDB\Model\BSONDocument)#40 (1) {
["storage":"ArrayObject":private]=>
array(2) {
["_id"]=>
object(MongoDB\BSON\ObjectID)#11 (1) {
["oid"]=>
string(24) "573b47a1f99a8d1f986278a5"
}
["persons"]=>
object(MongoDB\Model\BSONArray)#34 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
object(MongoDB\Model\BSONDocument)#10 (1) {
["storage":"ArrayObject":private]=>
array(1) {
["name"]=>
string(5) "Moshe"
}
}
[1]=>
object(MongoDB\Model\BSONDocument)#12 (1) {
["storage":"ArrayObject":private]=>
array(1) {
["name"]=>
string(1) "E"
}
}
}
}
}
}
}
这是PHP代码(全部):
function select(){
$conn = new MongoDB\Client("mongodb://localhost:27017");
$db = $conn->mydb;
$cursor = $db->entries_meta_data->find();
return current($cursor->toArray());
}
然后我用这样的json_encode将对象传递给客户端:
echo json_encode(select());
客户端出现的结果是:
{
"_id" : ObjectId("573b47a1f99a8a1f9a6278a5"),
"persons" : {
"0" : {
"name" : "Moshe",
},
"1" : {
"name" : "E",
}, ...
}
}
修改 LordNeo实际上解决了它。在阅读完答案后,我将“选择”功能中的最后一行更改为以下内容:
return json_decode(json_encode(current($cursor->toArray()),true);
它看起来很可怕,但确实有效。
我将非常乐意听到更好的解决方案。
答案 0 :(得分:3)
MongoDB驱动程序提供MongoDB\BSON\toJSON()
函数,可正确将数据转换为JSON。因为它需要一个字符串作为输入,所以首先需要在文档上调用MongoDB\BSON\fromPHP()
。
看起来您只想获得第一个找到的元素,您可以使用findOne()
方法而不是find()
,这样可以很容易地获得输出:
function select() {
$conn = new MongoDB\Client("mongodb://localhost:27017");
$db = $conn->mydb;
$doc = $db->entries_meta_data->findOne();
return MongoDB\BSON\toJSON(MongoDB\BSON\fromPHP($doc));
}
如果要输出多个条目,则会更复杂一些。这里显示了输出数组的一种(通常是hacky)方法:
function select() {
$conn = new MongoDB\Client("mongodb://localhost:27017");
$db = $conn->mydb;
$cursor = $db->entries_meta_data->find();
$result = $cursor->toArray();
foreach($result as $i => $doc) {
$result[$i] = MongoDB\BSON\toJSON(MongoDB\BSON\fromPHP($doc));
}
return '[' . implode($res) . ']';
}
另一种方法是在json_encode()
调用时调整BSONArray类的输出。为此,您需要调整位于“vendor / mongodb / mongodb / src / Model”文件夹中的setting up the MongoDB driver时获得的BSONArray.php文件,并添加JsonSerializable
接口和{{1方法,看起来像这样:
jsonSerialize()
答案 1 :(得分:3)
原因是new MongoDB driver处理MongoDB文档到不同于the old driver的PHP类型的转换。
好消息是,您可以通过指定所谓的"类型地图"来获得旧行为。
文档有点隐藏,但您可以阅读in the github repository of the driver或in the online docs。
TL; DR是你传递像
这样的数组array(
'array' => 'array',
'document' => 'array',
'root' => 'array'
)
作为第3个参数(" driverOptions")到MongoDB\Client的构造函数,或者为每个查询单独调用MongoDB\Driver\Cursor::setTypeMap()。
在你的例子中呼叫
$cursor->setTypeMap(array(
'array' => 'array',
'document' => 'array',
'root' => 'array'
));
$db->entries_meta_data->find()
之后应该做的伎俩。
答案 2 :(得分:2)
使用json_decode时,您可以使用可选的“true”参数,它将与数组相关联
$obj = json_decode($json, true);
//$obj will be an associative array
http://php.net/manual/en/function.json-decode.php
然后你可以使用array_shift剥离索引:
$obj = array_shift($obj);
http://php.net/manual/en/function.array-shift.php
JSON在未明确设置时添加数字索引,因此您应该将数组发送到客户端而不是解码 - >删除索引 - > enconding - >再次删除索引。
或者只是在客户收到索引后删除索引。
答案 3 :(得分:1)
是否存在从0到n的所有索引或者是否缺少任何索引?这可能是原因。如果要将其转换回数组,可以使用
$obj = select(); // changed by the new line added
然后
$obj['persons'] = array_values($obj['persons']);
摆脱指数。
我仍然非常确定缺少一些价值。但是从你的例子中看不出来。
答案 4 :(得分:0)
mthierer几乎有正确的解决方案。
实例化客户端时,需要将typeMap放入驱动程序选项(第3个参数)中。
var driver_options = {'typeMap'=> ['root':'array','document':'array','array':'array']}; var client = new MongoDB \ Client(conn,options,driver_options);
这比在每次实例化游标之后都必须执行此操作要好。