Laravel:无法 JSON 编码负载。错误代码:5
Laravel: Unable to JSON encode payload. Error code: 5
我正在开发 Laravel (v5.7) 应用程序,它将上传的 CSV(带有联系人)转换为数组,然后在调度作业 class 时将其作为参数传递。
这里是 CSV 文件的例子(支持的格式):
123456,Richard,Smith
654321,John,Doe
上传的 (CSV) 文件是这样处理的:
$file_path = $request->file_name->store('contacts');
$file = storage_path('app/' . $file_path);
$contactsIterator = $this->getContacts($file);
$contacts = iterator_to_array($contactsIterator); // Array of contacts from uploaded CSV file
protected function getContacts($file)
{
$f = fopen($file, 'r');
while ($line = fgets($f))
{
$row = explode(",", $line);
yield [
'phone' => !empty($row[0]) ? trim($row[0]) : '',
'firstname' => !empty($row[1]) ? trim($row[1]) : '',
'lastname' => !empty($row[2]) ? trim($row[2]) : '',
];
}
}
最后,$contacts
数组被传递给调度的作业:
ImportContacts::dispatch($contacts);
这份工作 class 看起来像这样:
public function __construct($contacts)
{
Log::info('ImportContacts@__construct START');
$this->contacts = $contacts;
Log::info('ImportContacts@__construct END');
}
public function handle()
{
Log::info('ImportContacts@handle');
}
...一切正常(没有错误),直到我尝试使用此 CSV:
123456,Richardÿ,Smith
654321,John,Doe
请注意ÿ
。因此,当我尝试使用此 CSV - 我收到此错误异常:
/code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5
...我的日志文件如下所示:
error local 2019-11-11 17:17:18 /code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5
info local 2019-11-11 17:17:18 ImportContacts@__construct END
info local 2019-11-11 17:17:18 ImportContacts@__construct START
如您所见 - handle
方法从未执行过。如果我删除 ÿ
- 没有错误并且 handle
被执行。
我已经尝试解决这个问题,但没有成功:
- 应用
utf8_encode
:
protected function getContacts($file, $listId)
{
$f = fopen($file, 'r');
while ($line = fgets($f))
{
$row = explode(",", $line);
yield [
'phone' => !empty($row[0]) ? utf8_encode($row[0]) : '',
'firstname' => !empty($row[1]) ? utf8_encode($row[1]) : '',
'lastname' => !empty($row[2]) ? utf8_encode($row[2]) : '',
];
}
}
... 它 有效 (没有错误,无论是否有 ÿ
),但随后希腊字母和西里尔字母变成了问号。例如,这个:Εθνικής
将变成 ???????
.
我也试过 mb_convert_encoding($row[1], 'utf-8')
- 它不会将希腊字母或西里尔字母变成问号,但是这个 ÿ
字符会变成 ?
.
- 将上传的 CSV 文件的“处理”(转换为数组)移动到作业的
@handle
方法中 class 有效,但我无法将该数组中的数据存储到数据库中(MongoDB)。请参阅下面的更新。
调试中:
这是我从 dd($contacts);
得到的:
所以,它有 ÿ
所在的“b”。而且,经过一番“谷歌搜索”后,我发现这个“b”的意思是“二进制字符串”,即非 unicode 字符串,函数在其上以字节级别运行 (What does the b in front of string literals do?)。
我的理解是:当调度工作 class 时,Laravel 试图“JSON 编码”它(通过 arguments/data)但它失败了,因为有二进制数据(非 unicode 字符串)。
无论如何,我无法找到解决方案(能够使用 ÿ
处理此类 CSV 文件)。
我正在使用:
- Laravel 5.7
- PHP 7.1.31-1+ubuntu16.04.1+deb.sury.org+1 (cli)(内置:2019 年 8 月 7 日 10:22:48)(NTS)
- Redis 驱动的队列
更新
当我将上传的 CSV 文件的“处理”(转换为数组)移动到作业的 @handle
方法时 class - 我没有收到此错误 (Unable to JSON encode payload. Error code: 5
) ,但是当我尝试将带有 ÿ
(b"Richardÿ"
) 的有问题的二进制数据存储到 MongoDB 中时 - 它失败了。奇怪的是,我在日志文件中没有收到任何错误异常 消息 ,所以我将所有内容都放在 try-catch 中,如下所示:
try {
// Insert data into MongoDB
} catch (Exception $e) {
Log::info($e->getFile());
Log::info($e->getLine());
Log::info($e->getMessage());
}
...这是结果:
无论如何,我认为它失败是因为 b"Richardÿ"
,我想解决方案是编码字符串,但正如我所提到的 - 我无法找到有效的解决方案:
utf8_encode
有效(没有错误,无论是否有 ÿ
),但随后希腊字母和西里尔字母变成了问号。例如,这:Εθνικής
将变为 ???????
mb_convert_encoding($row[1], 'utf-8')
- 它不会将希腊或西里尔字母变成问号,但是这个 ÿ
字符会变成 ?
.
iconv('windows-1252', 'UTF-8', $row[1])
- 有效(没有错误,无论是否有 ÿ
),但当有希腊字母或西里尔字母时 - 它失败(我收到此错误异常:iconv(): Detected an illegal character in input string
)
您有多种处理方法,但我推荐以下两种。在这两种情况下,想法都是存储 UTF-8 字符串。
更简单的方法,从(您的)预定义列表中找出它是什么编码并将其转换为 UTF8。
$encoding = mb_detect_encoding($content, 'UTF-8, ISO-8859-1, WINDOWS-1252, WINDOWS-1251', true);
if ($encoding != 'UTF-8') {
$string = iconv($encoding, 'UTF-8//IGNORE', $row[1]);
}
第二种方法是使用 this answer
中概述的第三方库
我正在开发 Laravel (v5.7) 应用程序,它将上传的 CSV(带有联系人)转换为数组,然后在调度作业 class 时将其作为参数传递。
这里是 CSV 文件的例子(支持的格式):
123456,Richard,Smith
654321,John,Doe
上传的 (CSV) 文件是这样处理的:
$file_path = $request->file_name->store('contacts');
$file = storage_path('app/' . $file_path);
$contactsIterator = $this->getContacts($file);
$contacts = iterator_to_array($contactsIterator); // Array of contacts from uploaded CSV file
protected function getContacts($file)
{
$f = fopen($file, 'r');
while ($line = fgets($f))
{
$row = explode(",", $line);
yield [
'phone' => !empty($row[0]) ? trim($row[0]) : '',
'firstname' => !empty($row[1]) ? trim($row[1]) : '',
'lastname' => !empty($row[2]) ? trim($row[2]) : '',
];
}
}
最后,$contacts
数组被传递给调度的作业:
ImportContacts::dispatch($contacts);
这份工作 class 看起来像这样:
public function __construct($contacts)
{
Log::info('ImportContacts@__construct START');
$this->contacts = $contacts;
Log::info('ImportContacts@__construct END');
}
public function handle()
{
Log::info('ImportContacts@handle');
}
...一切正常(没有错误),直到我尝试使用此 CSV:
123456,Richardÿ,Smith
654321,John,Doe
请注意ÿ
。因此,当我尝试使用此 CSV - 我收到此错误异常:
/code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5
...我的日志文件如下所示:
error local 2019-11-11 17:17:18 /code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5
info local 2019-11-11 17:17:18 ImportContacts@__construct END
info local 2019-11-11 17:17:18 ImportContacts@__construct START
如您所见 - handle
方法从未执行过。如果我删除 ÿ
- 没有错误并且 handle
被执行。
我已经尝试解决这个问题,但没有成功:
- 应用
utf8_encode
:
protected function getContacts($file, $listId)
{
$f = fopen($file, 'r');
while ($line = fgets($f))
{
$row = explode(",", $line);
yield [
'phone' => !empty($row[0]) ? utf8_encode($row[0]) : '',
'firstname' => !empty($row[1]) ? utf8_encode($row[1]) : '',
'lastname' => !empty($row[2]) ? utf8_encode($row[2]) : '',
];
}
}
... 它 有效 (没有错误,无论是否有 ÿ
),但随后希腊字母和西里尔字母变成了问号。例如,这个:Εθνικής
将变成 ???????
.
我也试过 mb_convert_encoding($row[1], 'utf-8')
- 它不会将希腊字母或西里尔字母变成问号,但是这个 ÿ
字符会变成 ?
.
- 将上传的 CSV 文件的“处理”(转换为数组)移动到作业的
@handle
方法中 class 有效,但我无法将该数组中的数据存储到数据库中(MongoDB)。请参阅下面的更新。
调试中:
这是我从 dd($contacts);
得到的:
所以,它有 ÿ
所在的“b”。而且,经过一番“谷歌搜索”后,我发现这个“b”的意思是“二进制字符串”,即非 unicode 字符串,函数在其上以字节级别运行 (What does the b in front of string literals do?)。
我的理解是:当调度工作 class 时,Laravel 试图“JSON 编码”它(通过 arguments/data)但它失败了,因为有二进制数据(非 unicode 字符串)。
无论如何,我无法找到解决方案(能够使用 ÿ
处理此类 CSV 文件)。
我正在使用:
- Laravel 5.7
- PHP 7.1.31-1+ubuntu16.04.1+deb.sury.org+1 (cli)(内置:2019 年 8 月 7 日 10:22:48)(NTS)
- Redis 驱动的队列
更新
当我将上传的 CSV 文件的“处理”(转换为数组)移动到作业的 @handle
方法时 class - 我没有收到此错误 (Unable to JSON encode payload. Error code: 5
) ,但是当我尝试将带有 ÿ
(b"Richardÿ"
) 的有问题的二进制数据存储到 MongoDB 中时 - 它失败了。奇怪的是,我在日志文件中没有收到任何错误异常 消息 ,所以我将所有内容都放在 try-catch 中,如下所示:
try {
// Insert data into MongoDB
} catch (Exception $e) {
Log::info($e->getFile());
Log::info($e->getLine());
Log::info($e->getMessage());
}
...这是结果:
无论如何,我认为它失败是因为 b"Richardÿ"
,我想解决方案是编码字符串,但正如我所提到的 - 我无法找到有效的解决方案:
utf8_encode
有效(没有错误,无论是否有ÿ
),但随后希腊字母和西里尔字母变成了问号。例如,这:Εθνικής
将变为???????
mb_convert_encoding($row[1], 'utf-8')
- 它不会将希腊或西里尔字母变成问号,但是这个ÿ
字符会变成?
.iconv('windows-1252', 'UTF-8', $row[1])
- 有效(没有错误,无论是否有ÿ
),但当有希腊字母或西里尔字母时 - 它失败(我收到此错误异常:iconv(): Detected an illegal character in input string
)
您有多种处理方法,但我推荐以下两种。在这两种情况下,想法都是存储 UTF-8 字符串。
更简单的方法,从(您的)预定义列表中找出它是什么编码并将其转换为 UTF8。
$encoding = mb_detect_encoding($content, 'UTF-8, ISO-8859-1, WINDOWS-1252, WINDOWS-1251', true);
if ($encoding != 'UTF-8') {
$string = iconv($encoding, 'UTF-8//IGNORE', $row[1]);
}
第二种方法是使用 this answer
中概述的第三方库