If an array is a packed array — i.e. empty array or the keys start at 0 and are sequential without gaps: BSON array.
If the array is not packed — i.e. having associative (string) keys, the keys don't start at 0, or when there are gaps:: BSON object
A top-level (root) document, always serializes as a BSON document.
These serialize as a BSON array:
[ 8, 5, 2, 3 ] => [ 8, 5, 2, 3 ] [ 0 => 4, 1 => 9 ] => [ 4, 9 ]
These serialize as a BSON document:
[ 0 => 1, 2 => 8, 3 => 12 ] => { "0" : 1, "2" : 8, "3" : 12 } [ "foo" => 42 ] => { "foo" : 42 } [ 1 => 9, 0 => 10 ] => { "1" : 9, "0" : 10 }
Note that the five examples are extracts of a full document, and represent only one value inside a document.
If an object is of the stdClass class, serialize as a BSON document.
If an object is a supported class that implements MongoDB\BSON\Type, then use the BSON serialization logic for that specific type. MongoDB\BSON\Type instances (excluding MongoDB\BSON\Serializable may only be serialized as a document field value. Attempting to serialize such an object as a root document will throw a MongoDB\Driver\Exception\UnexpectedValueException
If an object is of an unknown class implementing the MongoDB\BSON\Type interface, then throw a MongoDB\Driver\Exception\UnexpectedValueException
If an object is of any other class, without implementing any special interface, serialize as a BSON document. Keep only public properties, and ignore protected and private properties.
If an object is of a class that implements the MongoDB\BSON\Serializable interface, call MongoDB\BSON\Serializable::bsonSerialize() and use the returned array or stdClass to serialize as a BSON document or array. The BSON type will be determined by the following:
Root documents must be serialized as a BSON document.
MongoDB\BSON\Persistable objects must be serialized as a BSON document.
If MongoDB\BSON\Serializable::bsonSerialize() returns a packed array, serialize as a BSON array.
If MongoDB\BSON\Serializable::bsonSerialize() returns a non-packed array or stdClass, serialize as a BSON document.
If MongoDB\BSON\Serializable::bsonSerialize() did not return an array or stdClass, throw an MongoDB\Driver\Exception\UnexpectedValueException exception.
If an object is of a class that implements the
MongoDB\BSON\Persistable interface (which
implies MongoDB\BSON\Serializable), obtain
the properties in a similar way as in the previous paragraphs, but
also add an additional property
__pclass as a Binary value, with subtype
0x80
and data bearing the fully qualified class name
of the object that is being serialized.
The __pclass property is added to the array or object returned by MongoDB\BSON\Serializable::bsonSerialize(), which means it will overwrite any __pclass key/property in the MongoDB\BSON\Serializable::bsonSerialize() return value. If you want to avoid this behaviour and set your own __pclass value, you must not implement MongoDB\BSON\Persistable and should instead implement MongoDB\BSON\Serializable directly.
<?php
class stdClass
{
public $foo = 42;
} // => {"foo": 42}
class MyClass
{
public $foo = 42;
protected $prot = 'wine';
private $fpr = 'cheese';
} // => {"foo": 42}
class AnotherClass1 implements MongoDB\BSON\Serializable
{
public $foo = 42;
protected $prot = 'wine';
private $fpr = 'cheese';
public function bsonSerialize(): array
{
return ['foo' => $this->foo, 'prot' => $this->prot];
}
} // => {"foo": 42, "prot": "wine"}
class AnotherClass2 implements MongoDB\BSON\Serializable
{
public $foo = 42;
public function bsonSerialize(): self
{
return $this;
}
} // => MongoDB\Driver\Exception\UnexpectedValueException("bsonSerialize() did not return an array or stdClass")
class AnotherClass3 implements MongoDB\BSON\Serializable
{
private $elements = ['foo', 'bar'];
public function bsonSerialize(): array
{
return $this->elements;
}
} // => {"0": "foo", "1": "bar"}
/**
* Nesting Serializable classes
*/
class AnotherClass4 implements MongoDB\BSON\Serializable
{
private $elements = [0 => 'foo', 2 => 'bar'];
public function bsonSerialize(): array
{
return $this->elements;
}
} // => {"0": "foo", "2": "bar"}
class ContainerClass1 implements MongoDB\BSON\Serializable
{
public $things;
public function __construct()
{
$this->things = new AnotherClass4();
}
function bsonSerialize(): array
{
return ['things' => $this->things];
}
} // => {"things": {"0": "foo", "2": "bar"}}
class AnotherClass5 implements MongoDB\BSON\Serializable
{
private $elements = [0 => 'foo', 2 => 'bar'];
public function bsonSerialize(): array
{
return array_values($this->elements);
}
} // => {"0": "foo", "1": "bar"} as a root class
["foo", "bar"] as a nested value
class ContainerClass2 implements MongoDB\BSON\Serializable
{
public $things;
public function __construct()
{
$this->things = new AnotherClass5();
}
public function bsonSerialize(): array
{
return ['things' => $this->things];
}
} // => {"things": ["foo", "bar"]}
class AnotherClass6 implements MongoDB\BSON\Serializable
{
private $elements = ['foo', 'bar'];
function bsonSerialize(): object
{
return (object) $this->elements;
}
} // => {"0": "foo", "1": "bar"}
class ContainerClass3 implements MongoDB\BSON\Serializable
{
public $things;
public function __construct()
{
$this->things = new AnotherClass6();
}
public function bsonSerialize(): array
{
return ['things' => $this->things];
}
} // => {"things": {"0": "foo", "1": "bar"}}
class UpperClass implements MongoDB\BSON\Persistable
{
public $foo = 42;
protected $prot = 'wine';
private $fpr = 'cheese';
private $data;
public function bsonUnserialize(array $data): void
{
$this->data = $data;
}
public function bsonSerialize(): array
{
return ['foo' => $this->foo, 'prot' => $this->prot];
}
} // => {"foo": 42, "prot": "wine", "__pclass": {"$type": "80", "$binary": "VXBwZXJDbGFzcw=="}}
?>