序列化器

客户端有三种可用的序列化器。你可能永远都不会更改序列化器,除非你有特殊的要求或者需要实现新的协议。

序列化器的作用是编码发送的请求体并且解码请求的请求体。在 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() 方法:

  1. $client = ClientBuilder::create()
  2. ->setSerializer('\Elasticsearch\Serializers\SmartSerializer');
  3. ->build();

注意:要通过指定命名空间的方法来配置序列化器。

ArrayToJSONSerializer

Serialize()

所有需要编码的数据都会被 ArrayToJSONSerializer 检查。如果请求体提供的数据类型是字符串型,那么直接会发送给 Elasticsearch 。这种方式允许给没有结构的 endpoints (例如 Analyze endpoint)提供原生的 JSON 或者字符串。

如果数据是一个数组,则会被转换成 json。如果提供了空数组,序列化器则会把空数组([])转成空对象({}),这样发送给 Elasticsearch 的请求体都是有效的 json。

Deserialize()

当解码请求过来的请求体,所有的数据都会被解码成 json 。如果不是有效的 JSON ,那么将会返回 null

选择 ArrayToJSONSerializer

你可以在 ClientBuilder 对象中使用 setSerializer() 方法选择 ArrayToJSONSerializer

  1. $client = ClientBuilder::create()
  2. ->setSerializer('\Elasticsearch\Serializers\ArrayToJSONSerializer');
  3. ->build();

注意,序列化器是通过指定序列化器的命名空间路径来配置的。

EverythingToJSONSerializer

Serialize()

EverythingToJSONSerializer 试图将所有的数据都转成 JSON。

如果提供的数据是一个空数组,序列化器会手动将空数组([])转成空对象({}),这样提供给 Elasticsearch 的数据都是有效的 JSON。

如果数据不是数组或者无法转成 JSON,那么该方法将会返回 null

Deserialize()

当解码请求体的时候,所有的数据都会被解码成 JSON 格式。如果数据不是有效的 JSON ,那么将会返回 null

Selecting the EverythingToJSONSerializer

你可以在 ClientBuilder 对象中使用 setSerializer() 方法选择 EverythingToJSONSerializer

  1. $client = ClientBuilder::create()
  2. ->setSerializer('\Elasticsearch\Serializers\EverythingToJSONSerializer');
  3. ->build();

注意,序列化器是通过指定序列化器的命名空间路径来配置的。

实现自己的系列化

如果你想自定义系列化,你需要实现 SerializerInterface 接口。 请确保客户端所有的端点和连接使用单个系列化对象。

  1. class MyCustomSerializer implements SerializerInterface
  2. {
  3. /**
  4. * 系列化请求体
  5. *
  6. * @param string|array $data Request body
  7. *
  8. * @return string
  9. */
  10. public function serialize($data)
  11. {
  12. // code here
  13. }
  14. /**
  15. * 反系列化响应体
  16. *
  17. * @param string $data Response body
  18. * @param array $headers Response Headers
  19. *
  20. * @return array|string
  21. */
  22. public function deserialize($data, $headers)
  23. {
  24. // code here
  25. }
  26. }

然后你可以在 ClientBuilder 对象的 setSerializer() 方法中指定完整的命名空间来使用自定义系列化程序:

  1. $client = ClientBuilder::create()
  2. ->setSerializer('\MyProject\Serializers\MyCustomSerializer');
  3. ->build();

如果你的系列化程序具有构造函数或在发送到客户端之前需要初始化,只需要在实例化对象的时候提供依赖。

  1. $mySerializer = new MyCustomSerializer($a, $b, $c);
  2. $mySerializer->setFoo("bar");
  3. $client = ClientBuilder::create()
  4. ->setSerializer($mySerializer);
  5. ->build();