## Serialización a BSON

## Arrays

Si un array es un array compacto, esto es, las claves empiezan en 0 y están en secuencia sin huecos: array BSON.

Si el array no es compacto, esto es, tiene claves asociativas (string), las claves no comienzan en 0, o cuando hay huecos: objeto BSON

Un documento del más alto nivel (raíz), siempre se serializa como un documento BSON.

## Ejemplos

Los siguientes arrays se serializan como arrays BSON:

    [ 8, 5, 2, 3 ] => [ 8, 5, 2, 3 ]
    [ 0 => 4, 1 => 9 ] => [ 4, 9 ]

Estos se serializan como documentos BSON:

    [ 0 => 1, 2 => 8, 3 => 12 ] => { "0" : 1, "2" : 8, "3" : 12 }
    [ "foo" => 42 ] => { "foo" : 42 }
    [ 1 => 9, 0 => 10 ] => { "1" : 9, "0" : 10 }

Observe que los cinco ejemplos son fragmentos de un documento completo que representan solamente un valor dentro de un documento.

## Objetos

Si un objeto es de la clase stdClass se serializa como un documento BSON.

Si un objeto es de una clase admitida que implementa MongoDB\BSON\Tipo, se utiliza la lógica de serialización BSON para un tipo específico. Las instancias de MongoDB\BSON\Tipo (excluyendo MongoDB\BSON\Serializable solo podrían ser serializadas como un valor de campo de documento. Intentar serializar tales objetos como un documento raíz lanzará una MongoDB\Driver\Exception\UnexpectedValueException

Si un objeto se de una clase desconocida que implementa la interfaz MongoDB\BSON\Tipo, lanza una MongoDB\Driver\Exception\UnexpectedValueException

Si un objeto es de cualquier otra clase que no implemente ninguna interfaz especial, se serializa como un documento BSON. Se mantienen solo las propiedades public y se ignoran las propiedades protected y private.

Si un objeto es de una clase que implementa la interfaz MongoDB\BSON\Serializable, se llama a MongoDB\BSON\Serializable::bsonSerialize() y se utiliza el array u objeto stdClass devuelto para serilizarlo como un documento BSON o array. El tipo BSON será determinado como sigue:

1. Los documentos raíz deben ser serializados como un documento BSON.

2. Los objetos MongoDB\BSON\Persistable deben ser serializados como un documento BSON.

3. Si MongoDB\BSON\Serializable::bsonSerialize() devuelve un array compacto, se serializa como un array BSON.

4. Si MongoDB\BSON\Serializable::bsonSerialize() devuelve un array no compacto o un objeto stdClass, se serializa como un documento BSON.

5. Si MongoDB\BSON\Serializable::bsonSerialize() no devuelve un array u objeto stdClass, se lanza una excepción de tipo MongoDB\Driver\Exception\UnexpectedValueException.

Si un objeto es de una clase que implementa la interfaz MongoDB\BSON\Persistable (lo que implica que MongoDB\BSON\Serializable obtiene las propiedades de una forma similar a los párrafos anteriores, aunque también añade una propiedad adicional __pclass como un valor Binary, con subtipo `0x80` y datos soportando el nombre de la clase completamente cualificado del objeto que se está serializando.

La propiedad __pclass se añade al array u objeto devuelto por MongoDB\BSON\Serializable::bsonSerialize(), lo que significa que se sobrescribirá cualquier clave/propiedad __pclass en el valor devuelto de MongoDB\BSON\Serializable::bsonSerialize(). Para evitar este funcionamiento y establecer un valor de __pclass propio, no se debe implementar MongoDB\BSON\Persistable y, en su lugar, se deería implementar MongoDB\BSON\Serializable directamente.

## Ejemplos

`<?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";
function bsonSerialize() {
return [ 'foo' => $this->foo, 'prot' => $this->prot ];
}
} // => { "foo" : 42, "prot" : "wine" }
class AnotherClass2 implements MongoDB\BSON\Serializable {
public $foo = 42;
function bsonSerialize() {
return $this;
}
} // => MongoDB\Driver\Exception\UnexpectedValueException("bsonSerialize() did not return an array or stdClass")
class AnotherClass3 implements MongoDB\BSON\Serializable {
private $elements = [ 'foo', 'bar' ];
function bsonSerialize() {
return $this->elements;
}
} // => { "0" : "foo", "1" : "bar" }
class ContainerClass implements MongoDB\BSON\Serializable {
public $things = AnotherClass4 implements MongoDB\BSON\Serializable {
private $elements = [ 0 => 'foo', 2 => 'bar' ];
function bsonSerialize() {
return $this->elements;
}
}
function bsonSerialize() {
return [ 'things' => $this->things ];
}
} // => { "things" : { "0" : "foo", "2" : "bar" } }
class ContainerClass implements MongoDB\BSON\Serializable {
public $things = AnotherClass5 implements MongoDB\BSON\Serializable {
private $elements = [ 0 => 'foo', 2 => 'bar' ];
function bsonSerialize() {
return array_values($this->elements);
}
}
function bsonSerialize() {
return [ 'things' => $this->things ];
}
} // => { "things" : [ "foo", "bar" ] }
class ContainerClass implements MongoDB\BSON\Serializable {
public $things = AnotherClass6 implements MongoDB\BSON\Serializable {
private $elements = [ 'foo', 'bar' ];
function bsonSerialize() {
return (object) $this->elements;
}
}
function bsonSerialize() {
return [ 'things' => $this->things ];
}
} // => { "things" : { "0" : "foo", "1" : "bar" } }
class UpperClass implements MongoDB\BSON\Persistable {
public $foo = 42;
protected $prot = "wine";
private $fpr = "cheese";
function bsonSerialize() {
return [ 'foo' => $this->foo, 'prot' => $this->prot ];
}
} // => { "foo" : 42, "prot" : "wine", "__pclass" : { "$type" : "80", "$binary" : "VXBwZXJDbGFzcw==" } }`