Error malformed utf 8 data

I try to encrypt and decrypt this string using crypto-js: const str = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

I try to encrypt and decrypt this string using crypto-js:

const str = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1ZDg5MjMxMjc5OTkxYjJhNGMwMjdjMGIiLCJoc2giOiIkMmEkMTMkWk53Y0cubjdRZFIybDA3S1RHd2RoLlN0QksudW5GSFVGLkZnZ0tQTGlUV2pOVEFqVy9SMm0iLCJncmFudCI6ImFjY2VzcyIsImlhdCI6MTU2OTI2ODUwMiwiZXhwIjoxNjAwODI2MTAyfQ.PQcCoF9d25bBqr1U4IhJbylpnKTYiad3NjCh_LvMfLE~3~null~undefined~434ce0149ce42606d8746bd9`;

But I got an error:

Error: Malformed UTF-8 data

What I doing wrong? How do I fix that?

The full code also on stackbliz:

import crypto from 'crypto-js';

const str = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1ZDg5MjMxMjc5OTkxYjJhNGMwMjdjMGIiLCJoc2giOiIkMmEkMTMkWk53Y0cubjdRZFIybDA3S1RHd2RoLlN0QksudW5GSFVGLkZnZ0tQTGlUV2pOVEFqVy9SMm0iLCJncmFudCI6ImFjY2VzcyIsImlhdCI6MTU2OTI2ODUwMiwiZXhwIjoxNjAwODI2MTAyfQ.PQcCoF9d25bBqr1U4IhJbylpnKTYiad3NjCh_LvMfLE~9~null~undefined~434ce0149ce42606d8746bd9`;

const cryptoInfo = crypto.AES.encrypt(str, 'secret').toString();

console.log({ cryptoInfo });
const info2 = crypto.AES.decrypt(str, 'secret').toString(crypto.enc.Utf8);

console.log({ info2 });

asked Sep 26, 2019 at 7:46

Jon Sud's user avatar

2

Not sure why, but you have to wrap your string with an object and use JSON.stringify in order to make it works.

Here:

    import crypto from 'crypto-js';

    const str = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1ZDg5MjMxMjc5OTkxYjJhNGMwMjdjMGIiLCJoc2giOiIkMmEkMTMkWk53Y0cubjdRZFIybDA3S1RHd2RoLlN0QksudW5GSFVGLkZnZ0tQTGlUV2pOVEFqVy9SMm0iLCJncmFudCI6ImFjY2VzcyIsImlhdCI6MTU2OTI2ODUwMiwiZXhwIjoxNjAwODI2MTAyfQ.PQcCoF9d25bBqr1U4IhJbylpnKTYiad3NjCh_LvMfLE~9~null~undefined~434ce0149ce42606d8746bd9`;

    const cryptoInfo = crypto.AES.encrypt(JSON.stringify({ str }), 'secret').toString();

    console.log({ cryptoInfo });
    const info2 = crypto.AES.decrypt(cryptoInfo, 'secret').toString(crypto.enc.Utf8);

    console.log({ info2 });

    const info3 = JSON.parse(info2);

    console.log({ str: info3.str });

answered Sep 26, 2019 at 8:28

Shlomi Levi's user avatar

Shlomi LeviShlomi Levi

2,9951 gold badge22 silver badges32 bronze badges

I encrypt a name and pass it as URL parameter.
I was supprised, that the decrypt code did not work
It was because of the «+» char generated in the encrypted parameter. Then using «encodeURIComponent» and «decodeURIComponent» it worked.

<script>
jQuery("#myBtn").click(function(){
    var clientname= jQuery("#myInput").val();
    var encrypted  = CryptoJS.AES.encrypt(clientname, "secret key 123");
    //my URL to call with encrypted client name
    jQuery("#output").append('<small id="myurl">https://www.xxxxx.com/?id='+encodeURIComponent(encrypted)+"</small>");
});
</script>  



var urlParams = new URLSearchParams(window.location.search);
var crypted_param = decodeURIComponent(urlParams.get('id'));
if(crypted_param && crypted_param != null && crypted_param != "" && crypted_param != "null"){   
    var decrypted = CryptoJS.AES.decrypt(crypted_param, "secret key 123");
    jQuery('#output1').val(decrypted.toString(CryptoJS.enc.Utf8));
}
    

answered Sep 1, 2020 at 8:43

Severine's user avatar

You forgot to pass the encrypted text as parameter to decrypt function.

In decrypt function you are passing original string, i.e. ‘str’ which is causing the problem in above code, here is the corret code.

import crypto from "crypto-js";

const str = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1ZDg5MjMxMjc5OTkxYjJhNGMwMjdjMGIiLCJoc2giOiIkMmEkMTMkWk53Y0cubjdRZFIybDA3S1RHd2RoLlN0QksudW5GSFVGLkZnZ0tQTGlUV2pOVEFqVy9SMm0iLCJncmFudCI6ImFjY2VzcyIsImlhdCI6MTU2OTI2ODUwMiwiZXhwIjoxNjAwODI2MTAyfQ.PQcCoF9d25bBqr1U4IhJbylpnKTYiad3NjCh_LvMfLE~9~null~undefined~434ce0149ce42606d8746bd9`;

const cryptoInfo = crypto.AES.encrypt(JSON.stringify(str), "secret");

console.log({cryptoInfo});

const info2 = crypto.AES.decrypt(cryptoInfo.toString(), 'secret').toString(crypto.enc.Utf8);

console.log({ info2 });

answered Oct 16, 2020 at 9:16

Mahesh's user avatar

MaheshMahesh

1175 bronze badges

Despite all the above suggestions check your Encryption Key and Secret Key. While decrypting Encryption Key should match with your Encryption Key which you have used at the time of encrypting.

answered Mar 11, 2021 at 7:01

Ahmer Saeed's user avatar

Ahmer SaeedAhmer Saeed

5165 silver badges12 bronze badges

1

I was experiencing the same issue, it seems the encrypted value is base64 and needs to be converted to utf-8 first.
Example:

const utf8 = CryptoJS.enc.Base64.parse(value);
const decrypted = CryptoJS.DES.decrypt({ ciphertext: utf8 }, keyWords, { iv: ivWords });

I found the solution Here

answered Feb 22, 2022 at 7:56

Quintin Smith's user avatar

Might be this is slightly funny.. but this is how my senior has resolved this problem to me

We do have 2 different portals, assume XYZ portal and ABC portal (I am facing this issue in xyz portal)
ABC is the portal where we login.. to redirect to XYZ portal..

So in local I have opened both xyz portal and ABC portal.. and the issue is resolved..
(Earlier I opened only xyz portal so I was facing the issue) :D

answered Jul 14, 2022 at 6:33

Aliksm Shaik's user avatar

1

I’ve resolved my problem cleaning up the local storage.

enter image description here

legoscia's user avatar

legoscia

39.3k22 gold badges115 silver badges163 bronze badges

answered Jan 29, 2021 at 15:28

Camila Ferreira Ribeiro's user avatar

Содержание

  1. Malformed UTF-8 data #271
  2. Comments
  3. [Question] Knowing when decryption failed? #158
  4. Comments
  5. Решение типовых проблем с json_encode (PHP)
  6. Доступ к полям
  7. Решение
  8. Почему не стоит использовать подход с toJson методом?
  9. Что если у меня очень много полей в класcе?
  10. А если нужно private-поля, из класса, который нет возможности редактировать?
  11. Кодировка текстовых значений
  12. Кириллица и другие знаки в UTF8
  13. Символы в других кодировках
  14. Цифровые значения
  15. Error malformed utf 8 data
  16. Error malformed utf 8 data

Malformed UTF-8 data #271

I store the data in localstorage when encrypt(data, ducument.querySelector(‘.pwd’).value), then i try to call decrypt(localStorage.data, ducument.querySelector(‘.pwd’).value), it show the error:
Error: Malformed UTF-8 data

But when I try this encrypt(data, ‘123’) and decrypt(data, ‘123’), it is successful. and why?

cryptojs «version»: «4.0.0»,

The text was updated successfully, but these errors were encountered:

i am also getting same error

I also have the same problem. When I encrypt the data and decrypt them at the same time, everything is ok. But if I do some process and try it later I’m getting Error: Malformed UTF-8 data.

same error,anyone can help?

+1,same error,anyone can help?

thanks @cangyu1993 it was the solution for me =)

Now calculating the hash with the hashing scheme ‘HMAC-SHA256’ with the secret key 0F5DD14AE2

Resultant hash: c7689cda7474eb1adcd343fd0c0b676bad0ba66361cc46db589bdb0da4c1c867

Merchant should also ensure that UTF-8 encoding is used to convert the input from a printable string to a byte array. Also Note that 7-bit ASCII encoding is unchanged for UTF-8.

How Can I achieve that.

I followed the advice of cangyu1993 but could not resolve the problem!

So I took the following steps.

If there are any comrades who have the same problem, please refer to the following.

Replace this.configService.get(‘cryptoJs.secretKey’) => with your private key

The point was to composite and encrypt with CryptoJS.enc.Latin1

I got same error and after some debugging I realized , when we store encrypted data in the local storage it add «» at the starting and ending of the encrypted string. «»encrypted_string»» . when we try to decrypt our encrypted string that stored in localstorage , it try to decrypt it according to «enrypted_string» but it receives «»encrypted_string»» . therefore we receive this error from local storage. In otherword, it is because of mismatching our encrypted string.
what i did is replaced extra «» from string and then decrypted it. it worked for me

Источник

[Question] Knowing when decryption failed? #158

Is there anyway to know that decryption failed? specifically with AES?

Is there anyway to force the decryption process to maybe throw an exception for example?

Update: Work around for others, we’re for the time being storing a sha512 hash of the plain text before its encrypted, then once the decryption has finished, we take another sha512 of the result, and check if those hashes match to see if it was the original content. Not ideal but works currently

The text was updated successfully, but these errors were encountered:

Why not just check if decrypted == «» and then print out your own exception/try again/whatever?

@Phoenix1747 because if the thing you’re encrypting — happens to be empty you don’t know if it failed, or was just empty.

e.g imagine if you had a list of entries, each with «notes» field which needs to be encrypted as has something sensitive in it.

You don’t know when opening one of the entries if the decryption failed (then need to tell the user to re-enter their secret)

or if they just have not entered any notes yet.

You would assume that if you do something like «toString» and it fails — it will return a failure, or at least a way to signify a failure.

if it returned false on failure so you could do like if decrypted !== false then you know it failed.

or typically otherwise it would throw an exception

Источник

Решение типовых проблем с json_encode (PHP)

Это краткая статья о наиболее вероятных проблемах с json_encode и их решениях. Иногда при кодировании данных в json, с помощью json_encode в php, мы получаем не тот результат который ожидаем. Я выделил три наиболее частые проблемы с которыми сталкиваются программисты:

  • доступ к полям
  • кодировка текстовых значений
  • цифровые значения

Доступ к полям

Проблема заключается в том что json_encode имеет доступ только к публичным полям объекта. Например если у вас есть класс

то результатом выполнения следующего кода будет:

как видно в результирующий json были включены только публичные поля.
Что же делать если нужны все поля?

Решение

Для php = 5.4:
достаточно будет реализовать интерфейс JsonSerializable для нашего класса, что подразумевает добавление метода jsonSerialize который будет возвращать структуру представляющую объект для json_encode

Теперь мы можем использовать json_encode как и раньше

Почему не стоит использовать подход с toJson методом?

Многие наверно заметили что подход с созданием метода возвращающего json может быть использован и в версиях php >= 5.4. Так почему же не воспользоваться им? Все дело в том что ваш класс может быть использован как часть иной структуры данных

и результат уже будет совсем другой.
Также класс может использоваться другими программистами, для которых такой тип получение json-а с объекта может быть не совсем очевиден.

Что если у меня очень много полей в класcе?

В таком случае можно воспользоваться функцией get_object_vars

А если нужно private-поля, из класса, который нет возможности редактировать?

Может получиться ситуация когда нужно получить private поля (именно private, т.к. доступ к protected полям можно получить через наследование) в json-е. В таком случае необходимо будет воспользоваться рефлексией:

Кодировка текстовых значений

Кириллица и другие знаки в UTF8

Второй тип распространённых проблем с json_encode это проблемы с кодировкой. Часто текстовые значения которые нужно кодировать в json имеют в себе символы в UTF8 (в том числе кириллица) в результате эти символы будут представлены в виде кодов:

Отображение таких символов лечится очень просто — добавлением флага JSON_UNESCAPED_UNICODE вторым аргументом к функции json_encode:

Символы в других кодировках

Функция json_encode воспринимает строковые значения как строки в UTF8, что может вызвать ошибку, если кодировка другая. Рассмотрим маленький кусочек кода (данный пример кода максимально упрощен для демонстрации проблемной ситуации)

На первый взгляд ничего не предвещает проблем, да и что здесь может пойти не так? Я тоже так думал. В подавляющем большинстве случаев все будет работать, и по этой причине поиск проблемы занял у меня несколько больше времени, когда я впервые столкнулся с тем что результатом json_encode было false.

Для воссоздания такой ситуации предположим что p=%EF%F2%E8%F6%E0 (на пример: localhost?=%EF%F2%E8%F6%E0 ).
*Переменные в суперглобальных массивах $_GET и $_REQUEST уже декодированы.

Как можно увидеть из ошибки: проблема с кодировкой переданной строки (это не UTF8). Решение проблемы очевидное — привести значение в UTF8

Цифровые значения

Последняя типовая ошибка связана с кодированием числовых значений.

Как известно php не строго типизированный язык и позволяет использовать числа в виде строки, в большинстве случаев это не приводит к ошибкам внутри php приложения. Но так как json очень часто используется для передачи сообщений между приложениями, такой формат записи числа может вызвать проблемы в другом приложении. Желательно использовать флаг JSON_NUMERIC_CHECK:

Уже лучше. Но как видим «3.0» превратилось в 3, что в большинстве случаев будет интерпретировано как int. Используем еще один флаг JSON_PRESERVE_ZERO_FRACTION для корректного преобразования в float:

Прошу также обратить внимание на следующий фрагмент кода, что иллюстрирует ряд возможных проблем с json_encode и числовыми значениями:

Спасибо за прочтение.

Буду рад увидеть в комментариях описание проблем, с которыми вы сталкивались, что не были упомянуты в статье

Источник

Error malformed utf 8 data

Error encoding model [App\Models\Tenants\Employee] with ID [202] to JSON: Malformed UTF-8 characters, possibly incorrectly encodedn n

Here’s the situation; I’ve got a database with table full of employee data that includes a column ‘achternaam’ (lastname in Dutch), all of which are using utf8mb4_unicode_ci . We receive data from an external third party, parse it and put in our database. One of these employees we’ve imported has this surname: u00d6zyaprak — Tu00fczu00fcn. Yeah, that’s a lot of umlauts. n

Storing this in the database is no problem and the name is shown normally in Navicat. However, when I try try to parse that entity to JSON via a simple call of return response()->json(Employee::find(202)); I get the exception above. n

I’d love some ideas on what I or Laravel (e.g. via config) is doing wrong. n

JSON doesnt like non UTF-8 data. n

Try saving it as htmlentities before JSON encoding. n

n $test = array( ‘name’ => ‘u00d6zyaprak — Tu00fczu00fcn’ );n $test[‘bnamela’] = htmlentities( $test[‘name’] );nn echo json_encode( $test );n n

You can also try: n

return response()->json(Employee::find(202), 200, [], JSON_UNESCAPED_UNICODE); n n

I tried your first suggestion which worked. However, I’d now consider the data in my database to be faulty as the name would be stored as ‘u00d6zyaprak — Tu00fczu00fcn’. This would only cause more problems for the rest of the application. It doesn’t seem worth it to have to decode this everywhere I use it in the project (not just Blade/Vue). n

$employee = Employee::select(‘id’, ‘initialen’, ‘voornaam’, ‘achternaam’)->find(202);n$employee->achternaam = json_encode($employee->achternaam);nnreturn response()->json($employee);n n

Which gives us: n

Vue then shows this as n

«\u00d6zyaprak — T\u00fcz\u00fcn»n n

Could you try a couple more things for me please? Tinker would be great for rapidly testing this: n

public function getInitialsAttribute()n<n return substr($this->voornaam, 0, 1) . substr($this->achternaam, 0, 1);n>n n

This seemed to be the evil doer. The command you had me run in Tinker all show the following value for initials : n

=> [n «id» => 202,n «initialen» => «D.»,n «voornaam» => «Derya»,n «achternaam» => «u00d6zyaprak — Tu00fczu00fcn»,n «initials» => b»Du00c3″,n . n ]n n

b»Du00c3″ is not a very valid value =) I removed the attribute and everything worked. Now I just need to fix this little method but that’s a piece of cake. n

Could you try a couple more things for me please? Tinker would be great for rapidly testing this: n

rnWe don’t learn tools for the sake of learning tools. Instead, we learn them because they help us accomplish a particular goal. With that in mind, in this series, we’ll use the common desire for a blog — with categories, tags, comments, email notifications, and more — as our goal. Laravel will be the tool that helps us get there. Each lesson, geared toward newcomers to Laravel, will provide instructions and techniques that will get you to the finish line. rn rn

Источник

Error malformed utf 8 data

Error encoding model [App\Models\Tenants\Employee] with ID [202] to JSON: Malformed UTF-8 characters, possibly incorrectly encodedn n

Here’s the situation; I’ve got a database with table full of employee data that includes a column ‘achternaam’ (lastname in Dutch), all of which are using utf8mb4_unicode_ci . We receive data from an external third party, parse it and put in our database. One of these employees we’ve imported has this surname: u00d6zyaprak — Tu00fczu00fcn. Yeah, that’s a lot of umlauts. n

Storing this in the database is no problem and the name is shown normally in Navicat. However, when I try try to parse that entity to JSON via a simple call of return response()->json(Employee::find(202)); I get the exception above. n

I’d love some ideas on what I or Laravel (e.g. via config) is doing wrong. n

JSON doesnt like non UTF-8 data. n

Try saving it as htmlentities before JSON encoding. n

n $test = array( ‘name’ => ‘u00d6zyaprak — Tu00fczu00fcn’ );n $test[‘bnamela’] = htmlentities( $test[‘name’] );nn echo json_encode( $test );n n

You can also try: n

return response()->json(Employee::find(202), 200, [], JSON_UNESCAPED_UNICODE); n n

I tried your first suggestion which worked. However, I’d now consider the data in my database to be faulty as the name would be stored as ‘u00d6zyaprak — Tu00fczu00fcn’. This would only cause more problems for the rest of the application. It doesn’t seem worth it to have to decode this everywhere I use it in the project (not just Blade/Vue). n

$employee = Employee::select(‘id’, ‘initialen’, ‘voornaam’, ‘achternaam’)->find(202);n$employee->achternaam = json_encode($employee->achternaam);nnreturn response()->json($employee);n n

Which gives us: n

Vue then shows this as n

«\u00d6zyaprak — T\u00fcz\u00fcn»n n

Could you try a couple more things for me please? Tinker would be great for rapidly testing this: n

public function getInitialsAttribute()n<n return substr($this->voornaam, 0, 1) . substr($this->achternaam, 0, 1);n>n n

This seemed to be the evil doer. The command you had me run in Tinker all show the following value for initials : n

=> [n «id» => 202,n «initialen» => «D.»,n «voornaam» => «Derya»,n «achternaam» => «u00d6zyaprak — Tu00fczu00fcn»,n «initials» => b»Du00c3″,n . n ]n n

b»Du00c3″ is not a very valid value =) I removed the attribute and everything worked. Now I just need to fix this little method but that’s a piece of cake. n

Could you try a couple more things for me please? Tinker would be great for rapidly testing this: n

Источник

Here is a short blog for a problem I ran into this evening. I was testing a new endpoint that returns some user data in JSON format. Once every while the test was failing, it was flaky.

The error

The error was this one:
Malformed UTF-8 characters, possibly incorrectly encoded at /path/to/vendor/laravel/framework/src/Illuminate/Http/JsonResponse.php:75.

The cause

Since the problem only happened once every couple of tests (and helped by the error message itself) I figured it must be related to the random user that I test with.

This turned out to be true. When a name contains some accented character, like «Ç», this error occured.

The solution

The solution turned out to be in my application code, it has nothing to do with Laravel itself.

The initials of the user are part of the return data. So in case of a user named «Isabella Özkan», those would be «IÖ».

The old code for getting the initials was using strtoupper and substr like this:

public function initials(): string
{
    return strtoupper(substr($this->first_name, 0, 1) . substr($this->last_name, 0, 1));
}

But these functions are not multi-byte safe and so they can give incorrect results for multi-byte characters. To solve this we should use the equivalent multi-byte safe functions:

public function initials(): string
{
    return mb_strtoupper(mb_substr($this->first_name, 0, 1) . mb_substr($this->last_name, 0, 1));
}

That should do it. By using the correct string functions you make sure all characters are properly handled. This, in turn, will allow everything to be outputted as a JSON response without problems.

Happy coding!

Read some more

  • What is a command bus and why should you use it?.
  • Introduction into SSH keys.
  • Fixing Laravel Dusk error «This version of ChromeDriver only supports Chrome version xx».

Это краткая статья о наиболее вероятных проблемах с json_encode и их решениях. Иногда при кодировании данных в json, с помощью json_encode в php, мы получаем не тот результат который ожидаем. Я выделил три наиболее частые проблемы с которыми сталкиваются программисты:

  • доступ к полям
  • кодировка текстовых значений
  • цифровые значения

Доступ к полям

Проблема заключается в том что json_encode имеет доступ только к публичным полям объекта. Например если у вас есть класс

class Example {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }
}

то результатом выполнения следующего кода будет:

$obj = new Example("some", "value", "here"); 
echo json_encode($obj);

// {"publicProperty":"some"}

как видно в результирующий json были включены только публичные поля.
Что же делать если нужны все поля?

Решение

Для php < 5.4:
нам необходимо будет реализовать в классе метод который будет возвращать готовый json. Т.к. внутри класса есть доступ к всем полям можно сформировать правильное представление объекта для  json_encode

class Example {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }

    public function toJson()
    {
        return json_encode([
            'publicProperty' => $this->publicProperty,
            'protectedProperty' => $this->protectedProperty,
            'privateProperty' => $this->privateProperty,
        ]);
    }
}

Для получение json-a c объекта теперь нужно пользоваться методом toJson, а не прямым применением json_encode к объекту

$obj = new Example("some", "value", "here"); 
echo $obj->toJson();

Для php >= 5.4:
достаточно будет реализовать интерфейс JsonSerializable для нашего класса, что подразумевает добавление метода jsonSerialize который будет возвращать структуру представляющую объект для json_encode

class Example implements JsonSerializable
{
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }

    public function jsonSerialize() 
    {
        return [
            'publicProperty' => $this->publicProperty,
            'protectedProperty' => $this->protectedProperty,
            'privateProperty' => $this->privateProperty,
        ];
    }
}

Теперь мы можем использовать json_encode как и раньше

$obj = new Example("some", "value", "here"); 
echo json_encode($obj);

// {"publicProperty":"some","protectedProperty":"value","privateProperty":"here"}

Почему не стоит использовать подход с toJson методом?

Многие наверно заметили что подход с созданием метода возвращающего json может быть использован и в версиях php >= 5.4. Так почему же не воспользоваться им? Все дело в том что ваш класс может быть использован как часть иной структуры данных

echo json_encode([
    'status' => true,
    'message' => 'some message',
    'data' => new Example("some", "value", "here"),
]);

и результат уже будет совсем другой.
Также класс может использоваться другими программистами, для которых такой тип получение json-а с объекта может быть не совсем очевиден.

Что если у меня очень много полей в класcе?

В таком случае можно воспользоваться функцией get_object_vars

class Example implements JsonSerializable
{
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;
    protected $someProp1;
...
    protected $someProp100500;

    public function __construct($public, $protected, $private)
    {
        $this->publicProperty = $public;
        $this->protectedProperty = $protected;
        $this->privateProperty = $private;
    }

    public function jsonSerialize() 
    {
        $fields = get_object_vars($this);
        // что-то делаем ...
        return $fields;
    }
}

А если нужно private поля с класса который нет возможности редактировать?

Может получиться ситуация когда нужно получить private поля (именно private, т.к. доступ к protected полям можно получить через наследование) в json-е. В таком случае необходимо будет воспользоваться рефлексией:

class Example
{
    public $publicProperty = "someValue";
    protected $protectedProperty;
    private $privateProperty1;
    private $privateProperty2;
    private $privateProperty3;

    public function __construct($privateProperty1, $privateProperty2, $privateProperty3, $protectedProperty)
    {
        $this->protectedProperty = $protectedProperty;
        $this->privateProperty1 = $privateProperty1;
        $this->privateProperty2 = $privateProperty2;
        $this->privateProperty3 = $privateProperty3;
    }
}

$obj = new Example("value1", 12, "21E021", false);
$reflection = new ReflectionClass($obj);

$public = [];

foreach ($reflection->getProperties() as $property) {
    $property->setAccessible(true);
    $public[$property->getName()] = $property->getValue($obj);
}

echo json_encode($public);

//{"publicProperty":"someValue","protectedProperty":false,"privateProperty1":"value1","privateProperty2":12,"privateProperty3":"21E021"}

Кодировка текстовых значений

Кириллица и другие знаки в UTF8

Второй тип распространённых проблем с json_encode это проблемы с кодировкой. Часто текстовые значения которые нужно кодировать в json имеют в себе символы в UTF8 (в том числе кириллица) в результате эти символы будут представлены в виде кодов:

echo json_encode("кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $");

// "u043au0438u0440u0438u043bu043bu0438u0446u0430 or u20b3 u0192 u5143 ufdfc u20a8 u0bf9 uffe5 u20b4 uffe1 u0e3f uff04"

Отображение таких символов лечится очень просто — добавлением флага JSON_UNESCAPED_UNICODE вторым аргументом к функции json_encode:

echo json_encode("кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $", JSON_UNESCAPED_UNICODE);
// "кириллица or ₳ ƒ 元 ﷼ ₨ ௹ ¥ ₴ £ ฿ $"

Символы в других кодировках

Функция json_encode воспринимает строковые значения как строки в UTF8, что может вызвать ошибку, если кодировка другая. Рассмотрим маленький кусочек кода (данный пример кода максимально упрощен для демонстрации проблемной ситуации)

echo json_encode(["p" => $_GET['p']]);

На первый взгляд ничего не предвещает проблем, да и что здесь может пойти не так? Я тоже так думал. В подавляющем большинстве случаев все будет работать, и по этой причине поиск проблемы занял у меня несколько больше времени, когда я впервые столкнулся с тем что результатом json_encode было false.

Для воссоздания такой ситуации предположим что p=%EF%F2%E8%F6%E0 (на пример: localhost?=%EF%F2%E8%F6%E0 ).
*Переменные в суперглобальных массивах $_GET и $_REQUEST уже декодированы.

$decoded = urldecode("%EF%F2%E8%F6%E0");

var_dump(json_encode($decoded));
// bool(false)

var_dump(json_last_error_msg());
// string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

Как можно увидеть из ошибки: проблема с кодировкой переданной строки (это не UTF8). Решение проблемы очевидное — привести значение в UTF8

$decoded = urldecode("%EF%F2%E8%F6%E0");
$utf8 = utf8_encode($decoded);

echo json_encode($utf8);
// "ïòèöà"

Цифровые значения

Последняя типовая ошибка связана с кодированием числовых значений.

Например:

echo json_encode(["string_float" => "3.0"]);
// {"string_float":"3.0"}

Как известно php не строго типизированный язык и позволяет использовать числа записаны в виде строки, в большинстве случаев это не приводит к ошибкам внутри php приложения. Но так как json очень часто используется для передачи сообщений между приложениями, такой формат записи числа может вызвать проблемы в другом приложении. Желательно использовать флаг JSON_NUMERIC_CHECK:

echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK);
// {"string_float":3}

Уже лучше. Но как видим «3.0» превратилось в 3, что в большинстве случаев будет интерпретировано как int. Используем еще один флаг JSON_PRESERVE_ZERO_FRACTION для корректного преобразования в float:

echo json_encode(["string_float" => "3.0"], JSON_NUMERIC_CHECK | JSON_PRESERVE_ZERO_FRACTION);
// {"string_float":3.0}

Прошу так же обратить внимание на следующий фрагмент кода, что иллюстрирует ряд возможных проблем с json_encode и числовыми значениями:

$data = [
    "0000021", // нули слева
    6.12345678910111213, // много знаков после точки (будет округленно)
    "+81011321515", // телефон
    "21E021", // экспоненциальная запись
];

echo json_encode($data, JSON_NUMERIC_CHECK);
//[
//    21,
//    6.1234567891011,
//    81011321515,
//    2.1e+22
// ]

Спасибо за прочтение.

Буду рад увидеть в комментариях описание проблем, с которыми вы сталкивались, что не были упомянуты в статье

 

This error can be caused from many laravel modules such as Datatables, Json Output, Monolog … So this is a very difficult error to analyze and fix. In this article we try to find some way to fix that bug in laravel (in the common cases).

Why did you get this error? and how to fix it?

* Case 1: In case of failure due to wrong configuration of database connection

The most common is when you connect to a second database. Developers often have a configuration that lacks the «charset» and «collation» parameters, causing the error as you see it:

Exception Message:↵↵Malformed UTF-8 characters, possibly incorrectly encoded

To fix it please configure the connection parameters are complete.

Eg:

'mysql' => array(
            'driver'    => 'mysql',
            'host'      => 'localhost',
            'database'  => 'database_name_1',
            'username'  => 'user_1',
            'password'  => 'password_1'
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',

            'prefix'    => '',
    ....
 ),
/*mysql2 if you use two database*/
'mysql2' => array(
            'driver'    => 'mysql',
            'host'      => 'hostForDB2',
            'database'  => 'database_name_2',
            'username'  => 'user_2',
            'password'  => 'password_2'
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',

            'prefix'    => '',
    ...
),

* Case 2: Regex Error — Caused by some regex function in route, url validate ….

PREG_BAD_UTF8_ERROR 'Malformed UTF-8 characters, possibly incorrectly encoded'

*Case 3: JSON Encode, Json output error — Caused by Monolog, Datatables Logs..

To Fix Case 2 & 3 you can try converting the input to utf-8, or remove non-utf-8 characters.

Eg1: Function to auto convert any string to utf-8 encoding

$newString = mb_convert_encoding($inputString, "UTF-8", "auto");

Eg2: fix utf-8 encoding for Datatables column

$datatable->editColumn('title', function(Post $node) {
            return mb_convert_encoding($node->title,"UTF-8", "auto");
        });

Done ! For any other questions you can leave them in the comment section at the end of this article. Thank you.

Correct your file:


@tattoowizards wrote:

Hello guys.

I just installed Magento 2.3.2 on my local MAMP server, with composer.

Installation is completely clean. I do nothing yet.

The problem is — when I trying to configure Extension Manager after put my keys and pressing submit button I have this error message —  Unable to serialize value. Error: Malformed UTF-8 characters, possibly incorrectly encoded.

Please help me with this problem


Correct your file
..vendor/magento/framework/Serialize/Serializer/Json.php

use MagentoFrameworkSerializeSerializerInterface;

/**
 * Serialize data to JSON, unserialize JSON encoded data
 *
 * @api
 * @since 101.0.0
 */
class Json implements SerializerInterface
{
    /**
     * @inheritDoc
     * @since 101.0.0
     */
    public function serialize($data)
    {
        
        
        $result = json_encode(utf8ize($data));
        if (false === $result) {
            throw new InvalidArgumentException("Unable to serialize value2. Error: " . json_last_error_msg() );
        }
        return $result;
    }

    /**
     * @inheritDoc
     * @since 101.0.0
     */
    public function unserialize($string)
    {
        
        
        $result = json_decode($string, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new InvalidArgumentException("Unable to unserialize value. Error: " . json_last_error_msg());
        }
        return $result;
    }
    
}


function utf8ize( $mixed ) {
    if (is_array($mixed)) {
        foreach ($mixed as $key => $value) {
            $mixed[$key] = utf8ize($value);
        }
    } elseif (is_string($mixed)) {
        return mb_convert_encoding($mixed, "UTF-8", "UTF-8");
    }
    return $mixed;
}
        

Понравилась статья? Поделить с друзьями:
  • Error malformed statement
  • Error malformed list on input
  • Error malformed database schema
  • Error making static c
  • Error making sdcard fox directory required key not available