序列化器
客户端有三种可用的序列化器。你可能永远都不会更改序列化器,除非你有特殊的要求或者需要实现新的协议。
序列化器的作用是编码发送的请求体并且解码请求的请求体。在 99% 的案例中,这就是一种简单转换为JSON数据或解析 JSON 数据的工具。
默认的序列化器是 SmartSerializer
SmartSerializer
Serialize()
SmartSerializer
会检查需要编码的数据。如果请求体的数据是字符串,那么会直接发送给 Elasticsearch。这种方式允许给没有结构的 endpoints (例如 Analyze endpoint)提供原生的 JSON 或者字符串。
如果数据是数组,则会被转化成 json。如果提供的数据是一个空数组,序列化器会手动将空数组([]
)转成空对象({}
) ,这样发送给 Elasticsearch 的请求体都是有效的 json。
Deserialize()
当我们解码请求体时, SmartSerializer
会检测响应头的 content_type
来判断是否为合适的编码数据。如果数据传输过来是 JSON,那么可以使用 json_decode
转成数组。否则,则会返回字符串。
这个功能需要与 endpoints 一起协作,例如 Cat
endpoints 会返回表格文本而不是 JSON。
选择 SmartSerializer
默认的序列化器是 SmartSerializer ,如果你想明确的手动更改这个配置,你可以在 ClientBuilder 对象中使用 setSerializer()
方法:
$client = ClientBuilder::create()
->setSerializer('\Elasticsearch\Serializers\SmartSerializer');
->build();
注意:要通过指定命名空间的方法来配置序列化器。
ArrayToJSONSerializer
Serialize()
所有需要编码的数据都会被 ArrayToJSONSerializer
检查。如果请求体提供的数据类型是字符串型,那么直接会发送给 Elasticsearch 。这种方式允许给没有结构的 endpoints (例如 Analyze endpoint)提供原生的 JSON 或者字符串。
如果数据是一个数组,则会被转换成 json。如果提供了空数组,序列化器则会把空数组([]
)转成空对象({}
),这样发送给 Elasticsearch 的请求体都是有效的 json。
Deserialize()
当解码请求过来的请求体,所有的数据都会被解码成 json 。如果不是有效的 JSON ,那么将会返回 null
。
选择 ArrayToJSONSerializer
你可以在 ClientBuilder 对象中使用 setSerializer()
方法选择 ArrayToJSONSerializer
:
$client = ClientBuilder::create()
->setSerializer('\Elasticsearch\Serializers\ArrayToJSONSerializer');
->build();
注意,序列化器是通过指定序列化器的命名空间路径来配置的。
EverythingToJSONSerializer
Serialize()
EverythingToJSONSerializer
试图将所有的数据都转成 JSON。
如果提供的数据是一个空数组,序列化器会手动将空数组([]
)转成空对象({}
),这样提供给 Elasticsearch 的数据都是有效的 JSON。
如果数据不是数组或者无法转成 JSON,那么该方法将会返回 null
。
Deserialize()
当解码请求体的时候,所有的数据都会被解码成 JSON 格式。如果数据不是有效的 JSON ,那么将会返回 null
。
Selecting the EverythingToJSONSerializer
你可以在 ClientBuilder 对象中使用 setSerializer()
方法选择 EverythingToJSONSerializer
:
$client = ClientBuilder::create()
->setSerializer('\Elasticsearch\Serializers\EverythingToJSONSerializer');
->build();
注意,序列化器是通过指定序列化器的命名空间路径来配置的。
实现自己的系列化
如果你想自定义系列化,你需要实现 SerializerInterface
接口。 请确保客户端所有的端点和连接使用单个系列化对象。
class MyCustomSerializer implements SerializerInterface
{
/**
* 系列化请求体
*
* @param string|array $data Request body
*
* @return string
*/
public function serialize($data)
{
// code here
}
/**
* 反系列化响应体
*
* @param string $data Response body
* @param array $headers Response Headers
*
* @return array|string
*/
public function deserialize($data, $headers)
{
// code here
}
}
然后你可以在 ClientBuilder 对象的 setSerializer()
方法中指定完整的命名空间来使用自定义系列化程序:
$client = ClientBuilder::create()
->setSerializer('\MyProject\Serializers\MyCustomSerializer');
->build();
如果你的系列化程序具有构造函数或在发送到客户端之前需要初始化,只需要在实例化对象的时候提供依赖。
$mySerializer = new MyCustomSerializer($a, $b, $c);
$mySerializer->setFoo("bar");
$client = ClientBuilder::create()
->setSerializer($mySerializer);
->build();