序列化器

优质
小牛编辑
132浏览
2023-12-01

客户端有 3 种序列化器可用。你可能永远都不会更改序列化器,除非你有特殊需求或者要实现一个新的协议。 序列化器的工作是 encode 发送的请求体和 decode 返回的响应体。在 99% 的例子中,这就是一种简单转换为JSON数据或解析 JSON 数据的工具。 默认的序列化器是 SmartSerializer

SmartSerializer

Serialize()

SmartSerializer 会先检查需要 encode 的数据。如果请求体是字符串,那么会直接发送到 Elasticsearch。这种方式允许用户提供原生JSON数据,或是字符串(提供给某些没有结构的 endpoint,例如 Analyze endpoint)。 如果数据是数组,则会被转换为 JSON 数据。如果数据是空数组,那么序列化器需要手动转换空数组( [] )为空对象( {} ),这样发送给 Elasticsearch 的请求体数据才是有效的 JSON 数据。

Deserialize()

当 decode 响应体数据时, SmartSerializer 会检测响应头的 content_type 来判断是否为合适的encode数据。假如数据 encode 为 JSON 数据,那么会用 json_decode 来解析 JSON 数据为数组。否则会以字符串的格式返回给客户端。 这个功能需要与 endpoint 协作,例如 Cat endpoints 会返回表格文本而非 JSON 数据。

选择 SmartSerializer

客户端默认选择 SmartSerializer ,但如果你想手动地配置这个选择器,你可以在 ClientBuilder 对象中使用 setSerializer() 方法:

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

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

ArrayToJSONSerializer

Serialize()

ArrayToJSONSerializer 会先检查需要 encode 的数据。如果请求体是字符串,那么会直接发送到 Elasticsearch。这种方式允许用户提供原生 JSON 数据,或是字符串(提供给某些没有结构的 endpoint,例如 Analyze endpoint)。 如果数据是数组,则会被转换为 JSON 数据。如果数据是空数组,那么序列化器需要手动转换空数组( [] )为空对象( {} ),这样发送给 Elasticsearch 的请求体数据才是有效的 JSON 数据。

Deserialize()

当 decode 响应体数据时,所有数据都会 encode 由 JSON 数据 decode 为 JSON 数据。如果数据不是有效的 JSON 数据,那么会返回 null 给客户端。

选择 ArrayToJSONSerializer

你可以通过使用 ClientBuilder 对象的 setSerializer() 方法来选择 ArrayToJSONSerializer

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

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

EverythingToJSONSerializer

Serialize()

EverythingToJSONSerializer 会把一切数据转换为JSON数据。 如果数据是空数组,那么序列化器需要手动转换空数组( [] )为空对象( {} ),这样发送给 Elasticsearch 的请求体数据才是有效的 JSON 数据。 如果数据不是数组且(或)没有转换为 JSON 数据,那么这个方法会返回 null 给客户端。

Deserialize()

当 decode 响应体数据时,所有数据都会 encode 由 JSON 数据 decode 为 JSON 数据。如果数据不是有效的 JSON 数据,那么会返回 null 给客户端。

选择 EverythingToJSONSerializer

你可以通过使用 ClientBuilder 对象的 setSerializer() 方法来选择 EverythingToJSONSerializer

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

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

实现自定义序列化器

如果你想使用自定义序列器,你需要实现 SerializerInterface 接口。请记住,对于所有的 endpoint 和连接来说,客户端只使用一个序列器对象。

class MyCustomSerializer implements SerializerInterface
{

    /**
     * Serialize request body
     *
     * @param string|array $data Request body
     *
     * @return string
     */
    public function serialize($data)
    {
        // code here
    }

    /**
     * Deserialize response body
     *
     * @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();