Laravel:无法JSON编码有效负载.错误代码:5 [英] Laravel: Unable to JSON encode payload. Error code: 5

查看:152
本文介绍了Laravel:无法JSON编码有效负载.错误代码:5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Laravel(v5.7)应用程序,该应用程序将上传的CSV(带有联系人)转换为数组,然后在调度作业类时将其作为参数传递.

以下是CSV文件(支持的格式)的示例:

  123456,Richard,Smith654321,约翰·多伊 

上传(CSV)文件的处理方式如下:

 <代码> $ file_path = $ request-> file_name-> store('contacts');$ file = storage_path('app/'.$ file_path);$ contactsIterator = $ this-> getContacts($ file);$ contacts = iterator_to_array($ contactsIterator);//来自上传的CSV文件的联系人数组 

 受保护的函数getContacts($ file){$ f = fopen($ file,'r');而($ line = fgets($ f)){$ row = explode(,",$ line);屈服 ['电话'=>!empty($ row [0])吗?trim($ row [0]):'','名字'=>!empty($ row [1])吗?trim($ row [1]):'','姓氏'=>!empty($ row [2])吗?trim($ row [2]):'',];}} 

最后,将 $ contacts 数组传递给已调度的作业:

  ImportContacts :: dispatch($ contacts); 

此工作类别如下:

 公共函数__construct($ contacts){Log :: info('ImportContacts @__ construct START');$ this->联系人= $联系人;Log :: info('ImportContacts @__ construct END');}公共功能handle(){日志:: info('ImportContacts @ handle');} 

...,在我尝试使用此CSV之前,一切正常(没有错误):

  123456,Richardÿ,Smith654321,约翰·多伊 

请注意ÿ.因此,当我尝试使用此CSV时-出现此错误异常:

 /code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php |91 |无法JSON编码有效负载.错误代码:5 

...,我的日志文件如下所示:

 本地错误2019-11-11 17:17:18/code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php |91 |无法JSON编码有效负载.错误代码:5信息本地2019-11-11 17:17:18 ImportContacts @__ construct END信息本地2019-11-11 17:17:18 ImportContacts @__ construct START 

您可以看到-从未执行过 handle 方法.如果我删除ÿ-没有错误,并且执行了 handle .

我试图解决这个问题,但没有成功:

  1. 应用 utf8_encode :

 受保护的函数getContacts($ file,$ listId){$ f = fopen($ file,'r');而($ line = fgets($ f)){$ row = explode(,",$ line);屈服 ['电话'=>!empty($ row [0])吗?utf8_encode($ row [0]):'','名字'=>!empty($ row [1])吗?utf8_encode($ row [1]):'','姓氏'=>!empty($ row [2])吗?utf8_encode($ row [2]):'',];}} 

...并且它有效(没有错误,无论是否有ÿ),但是随后希腊字母和西里尔字母变成了问号.例如,这:Εθνικής将变为 ??????? .

我还尝试了 mb_convert_encoding($ row [1],'utf-8')-它不会将希腊字母或西里尔字母变成问号,但这是ÿ字符将变为?.

  1. 移动处理"(转换为数组)将上传的CSV文件转换为Job类的 @handle 方法有效,但是后来我无法将该数组中的数据存储到DB(MongoDB)中.请参阅下面的更新.


调试:

这是我从 dd($ contacts); :

因此,它具有"b"ÿ在哪里.并且,在经过一些搜索"之后,我发现这个"b"表示二进制字符串",即非Unicode字符串,其功能在字节级别上操作(

无论如何,我相信它是由于 b"Richardÿ" 而失败的,我想解决方案是在编码字符串中,但是正如我已经提到的那样-我无法找到解决方案可行:

  • utf8_encode 可以工作(没有错误,无论是否有ÿ),但是希腊字母和西里尔字母变成了问号.例如,这:Εθνικής将变为 ???????
  • mb_convert_encoding($ row [1],'utf-8')-它不会将希腊字母或西里尔字母变成问号,但是此ÿ字符会成为?.
  • iconv('windows-1252','UTF-8',$ row [1])-有效(无错误,无论是否有ÿ,但是当有希腊字母或西里尔字母时-会失败(我收到此错误异常: iconv():在输入字符串中检测到非法字符)

解决方案

您可以通过几种方法来处理它,但我建议以下两种方法.在这两种情况下,其想法都是存储UTF-8字符串.

一种更简单的方法,从(您的)预定义列表中找出它是哪种编码,然后将其转换为UTF8.

  $ encoding = mb_detect_encoding($ content,'UTF-8,ISO-8859-1,WINDOWS-1252,WINDOWS-1251',true);如果($ encoding!='UTF-8'){$ string = iconv($ encoding,'UTF-8//IGNORE',$ row [1]);} 

第二种方法是使用此答案

中概述的第三方库

I'm working on Laravel (v5.7) app that converts uploaded CSV (with contacts) into array that is then passed as argument when job class is being dispatched.

Here is the example of CSV file (format that is supported):

123456,Richard,Smith
654321,John,Doe

Uploaded (CSV) file is handled like this:

$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]) : '',
            ];
        }
    }

Finally, $contacts array is passed to a job that is dispatched:

ImportContacts::dispatch($contacts);

This job class looks like this:

    public function __construct($contacts)
    {
        Log::info('ImportContacts@__construct START');
        $this->contacts = $contacts;
        Log::info('ImportContacts@__construct END');
    }

    public function handle()
    {
        Log::info('ImportContacts@handle');
    }

... and everything worked fine (no errors) until I've tried with this CSV:

123456,Richardÿ,Smith
654321,John,Doe

Please notice ÿ. So, when I try with this CSV - I get this error exception:

/code_smsto/vendor/laravel/framework/src/Illuminate/Queue/Queue.php | 91 | Unable to JSON encode payload. Error code: 5 

... and my log file looks like this:

  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 

As you can see - handle method was never executed. If I remove ÿ - no errors and handle is executed.

I've tried to solve this, but without success:

  1. Apply 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]) : '',
            ];
        }
    }

... and it works (no errors, no matter if there's that ÿ), but then Greek and Cyrillic letters are turned into question marks. For example, this: Εθνικής will become ???????.

I also tried with mb_convert_encoding($row[1], 'utf-8') - and it doesn't turn Greek or Cyrillic letter into question marks, but this ÿ character will become ?.

  1. Move "handling" (converting to array) of uploaded CSV file into @handle method of a Job class worked, but then I was not able to store the data from that array into DB (MongoDB). Please see the update below.


DEBUGGING:

This is what I get from dd($contacts);:

So, it has that "b" where ÿ is. And, after some "googling" I found that this "b" means "binary string", that is, a non unicode string, on which functions operate at the byte level (What does the b in front of string literals do?).

What I understand is this: When dispatching Job class, Laravel tries to "JSON encode" it (passed arguments/data) but it fails because there are binary data (non-unicode strings). Anyway, I was not able to find a solution (to be able to handle such CSV file with ÿ).

I am using:

  • Laravel 5.7
  • PHP 7.1.31-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Aug 7 2019 10:22:48) ( NTS )
  • Redis powered queues

UPDATE

When I move "handling" (converting to array) of uploaded CSV file into @handle method of a Job class - I don't get this error (Unable to JSON encode payload. Error code: 5), but when I try to store that problematic binary data with ÿ (b"Richardÿ") into MongoDB - it fails. The weird thing is that I don't get any error-exception message in log file, so I put all in try-catch like this:

        try {
            // Insert data into MongoDB
        } catch (Exception $e) {
            Log::info($e->getFile());
            Log::info($e->getLine());
            Log::info($e->getMessage());
        }

... and this is the result:

Anyway, I believe that it failed because of b"Richardÿ", and I guess that the solution is in encoding string, but as I've mentioned - I was not able to find a solution that works:

  • utf8_encode works (no errors, no matter if there's that ÿ), but then Greek and Cyrillic letters are turned into question marks. For example, this: Εθνικής will become ???????
  • mb_convert_encoding($row[1], 'utf-8') - it doesn't turn Greek or Cyrillic letter into question marks, but this ÿ character will become ?.
  • iconv('windows-1252', 'UTF-8', $row[1]) - works (no errors, no matter if there's that ÿ), but when there are Greek or Cyrillic letters - it fails (I get this error exception: iconv(): Detected an illegal character in input string)

解决方案

You have several ways to deal with it but I'd recommend the following two. In both cases, the idea is that you store a UTF-8 string.

A simpler approach, figure out what encoding it is out of the (your) predefined list and convert it to 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]);
}

The second approach is to use a third party library outlined in this answer

这篇关于Laravel:无法JSON编码有效负载.错误代码:5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆