diff --git a/src/Elasticsearch/Serializers/SmartSerializer.php b/src/Elasticsearch/Serializers/SmartSerializer.php index dac88dee3..3a79ff188 100644 --- a/src/Elasticsearch/Serializers/SmartSerializer.php +++ b/src/Elasticsearch/Serializers/SmartSerializer.php @@ -20,6 +20,7 @@ use Elasticsearch\Common\Exceptions; use Elasticsearch\Common\Exceptions\Serializer\JsonErrorException; +use JsonException; if (!defined('JSON_INVALID_UTF8_SUBSTITUTE')) { //PHP < 7.2 Define it as 0 so it does nothing @@ -84,9 +85,18 @@ private function decode(?string $data): array try { $result = json_decode($data, true, 512, JSON_THROW_ON_ERROR); return $result; - } catch (\JsonException $e) { - $result = $result ?? []; - throw new JsonErrorException($e->getCode(), $data, $result); + } catch (JsonException $e) { + switch ($e->getCode()) { + case JSON_ERROR_UTF16: + try { + $data = str_replace('\\', '\\\\', $data); + $result = json_decode($data, true, 512, JSON_THROW_ON_ERROR); + return $result; + } catch (JsonException $e) { + throw new JsonErrorException($e->getCode(), $data, $result ?? []); + } + } + throw new JsonErrorException($e->getCode(), $data, $result ?? []); } } diff --git a/tests/Elasticsearch/Tests/Serializers/SmartSerializerTest.php b/tests/Elasticsearch/Tests/Serializers/SmartSerializerTest.php index 7ad77e794..96ad30c56 100644 --- a/tests/Elasticsearch/Tests/Serializers/SmartSerializerTest.php +++ b/tests/Elasticsearch/Tests/Serializers/SmartSerializerTest.php @@ -45,4 +45,18 @@ public function testThrowJsonErrorException() $result = $this->serializer->deserialize('{ "foo" : bar" }', []); } + + /** + * Single unpaired UTF-16 surrogate in unicode escape + * + * @requires PHP 7.3 + * @see https://github.com/elastic/elasticsearch-php/issues/1171 + */ + public function testSingleUnpairedUTF16SurrogateInUnicodeEscape() + { + $json = '{ "data": "ud83d\ude4f" }'; + + $result = $this->serializer->deserialize($json, []); + $this->assertEquals($result['data'], 'ud83d\ude4f'); + } }