When I dump the property of my model and it has an accent it returns with this "b" prefix
dump($venda_item->produto->nomeproduto); // b"teste téste"
My database is setted to utf8 and utf8_general_ci collation
This causes me the following error Malformed UTF-8 characters, possibly incorrectly encoded when I'm returning the response in json, at this line
$json_response = Response::json($response, $this->getStatusCode(), $headers);
Update
I discovered that if I die and dump the record on the web route it shows normal teste téste
Route::get('/', function () {
dd(App\Vendasitem::where('codigovi', 112685)->first()->produto->nomeproduto);
}
otherwise if I do the same in the controller or request and other files that I tryied it keeps returning me with the "b" prefix
Update 2
If I save my record like this PROMO - VIRICAPS (GUARANá + POLIVIT) 60 CáPS - CAIXA 18 UND and dump($venda_item->produto->nomeproduto); it returns me the right result with the accents.
All my database, including the column is set up to utf8mb4 and utf8mb4_unicode_ci
If you already confirmed the encoding on your database. Have a look on config/database.php, on charset and collation proprieties.
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci'
If the issue is on the "print" then you might use the utf8_encode function.
{{utf8_encode($yourVar)}}
I had this problem when importing data from a different database. Solved with this method, maybe it works for you to.
public function fixEncoding($str) {
return mb_check_encoding($str, 'UTF-8')
? html_entity_decode($str)
: utf8_encode(html_entity_decode($str));
}
So, it looks like your best bet is to write a accessor for the object using iconv:
public function getNomeprodutoAttribute($value) {
return iconv("utf-8", "utf-8//ignore", $value);
}
Unless you want to recode the whole database, which probably isn't an option.
The value passed in will the value out of the database (which is the unfortunate binary data). Then you are telling it the input is utf (which it is), and that the output is utf8 (which we want) but to ignore chars that aren't supported in utf-8. //ignore may work in some versions of the library, so you'd just have to do the following, and hope for the best:
public function getNomeprodutoAttribute($value) {
return iconv("utf-8", "utf-8", $value);
}
Use this function
public function utf8ize($value) {
if (is_array($value)) {
foreach ($value as $k => $v) {
$value[$k] = utf8ize($v);
}
} else if (is_string ($value)) {
return utf8_encode($value);
}
return $value;
}
Related
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:
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 ?.
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
I have a stdClass object called $post that, when dumped via print_r(), returns the following:
stdClass Object (
[ID] => 12981
[post_title] => Alumnus' Dinner Coming Soon
[post_parent] => 0
[post_date] => 2012-01-31 12:00:51
)
Echoing the result from calling json_encode() on this object results in the following:
{
"ID": "12981",
"post_title": null,
"post_parent": "0",
"post_date": "2012-01-31 12:00:51"
}
I'm assuming that something with the single quote is causing json_encode to choke, but I don't know what format is needed to escape that. Any ideas?
EDIT: Fixed mismatch in code examples. I'm running PHP version 5.3.8
EDIT2: Directly after encoding the object, I did this:
echo json_last_error() == JSON_ERROR_UTF8;
This printed 1, which means that the following error occurred: "Malformed UTF-8 characters, possibly incorrectly encoded". json_last_error()
EDIT3: Calling utf8_decode() on the post title resulted in the following: "Alumnus? Dinner Coming Soon". This data is being pulled from a MySQL database - the post title in particular is a text field, UTF-8 encoded. Maybe this single-quote is improperly encoded? The thing is, I have a SQL GUI app, and it appears correctly in that.
You need to set the connection encoding before executing queries. How this is done depends on the API you are using to connect:
call mysql_set_charset("utf8") if you use the old, deprecated API.
call mysqli_set_charset("utf8") if you use mysqli
add the charset parameter to the connection string if you use PDO and PHP >= 5.3.6. In earlier versions you need to execute SET NAMES utf8.
When you obtain data from MySQL any text will be encoded in "client encoding", which is likely windows-1252 if you don't configure it otherwise. The character that is causing your problem is the "curly quote", seen as 92 in the hex dump, which confirms that the mysql client is encoding text in windows-1252.
Another thing you might consider is pass all text through utf8_encode, but in this case it wouldn't produce the correct result. PHP's utf8_encode converts iso-8859-1-encoded text. In this encoding \x92 is a non-printable control character, which would be converted into a non-printable control character in utf-8. You could use str_replace("\x92", "'", $input) to fix the problem for this particular character, but if there's any chance there will be any other non-ascii characters in the database you'll want to have the client use UTF-8.
What I've had to do in the past to json_encode on text with utf8 characters is
json_encode( utf8_encode( $s ) );
and in some cases
json_encode( htmlspecialchars( utf8_encode( $s ) ) );
the utf8_encode() to handle special characters (note, that's Encode, not Decode)
the htmlspecialchars() depending on how you mean to use the JSON string, you may be able to leave this out
and finally, json_encode() to get your JSON packet.
Since you want to json_encode an object, you would need to call utf8_encode() on each text part first, or write a simple recursive utf8_encode(). For your example case, this would do:
function myEncode($o) {
$o->title = utf8_encode($o->title);
return json_encode($o);
}
I would like to refer you about this issue,
on link
I suggest you use a json_encode wrapper like this :
function safe_json_encode($value){
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$encoded = json_encode($value, JSON_PRETTY_PRINT);
} else {
$encoded = json_encode($value);
}
switch (json_last_error()) {
case JSON_ERROR_NONE:
return $encoded;
case JSON_ERROR_DEPTH:
return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
case JSON_ERROR_STATE_MISMATCH:
return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
case JSON_ERROR_CTRL_CHAR:
return 'Unexpected control character found';
case JSON_ERROR_SYNTAX:
return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
case JSON_ERROR_UTF8:
$clean = utf8ize($value);
return safe_json_encode($clean);
default:
return 'Unknown error'; // or trigger_error() or throw new Exception()
}
}
function utf8ize($mixed) {
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = utf8ize($value);
}
} else if (is_string ($mixed)) {
return utf8_encode($mixed);
}
return $mixed;
}
And after define these function you can use it direct,
echo safe_json_encode($response);
i was having the same issue while JSON encoding a php array from an ODBC query results, my Server's OBC is configured with 'en_US.819', is a production server so there is no way i can even touch that!!.
when i tried:
echo json_encode($GLOBALS['response'], true);
Where 'respose' is an array with the results, it works as intended as long no bizarre char is present, if so, json_encode fails returning empty.
The solution?.... UTF encode results while fetching the rows from query:
$result = odbc_exec($conn, $sql_query);
$response = array();
while( $row = odbc_fetch_array($result) ) {
$json['pers_identificador'] = $row['pers_identificador'];
$json['nombre_persona'] = utf8_encode( $row['nombre_persona'] );
$json['nombre_1'] = utf8_encode($row['nombre_1'] );
$json['nombre_2'] = utf8_encode($row['nombre_2'] );
array_push($response, $json);
}
Now json_encode works!!!, the resulting string is something like this:
{"page_id":300,"max_rows":"100","cant_rows":"12897","datos":
[{"pers_identificador":"301","cedula":"15250068","interno_1":"178202","interno_2":"","nombre_persona":"JOSE JUAN PANDOLFO ZAGORODKO","nombre_1":"JOSE","nombre_2":"JUAN",....
That fixed my issue.
You can try to set the charset in the database config:
'charset' => 'utf8',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
)
I have a stdClass object called $post that, when dumped via print_r(), returns the following:
stdClass Object (
[ID] => 12981
[post_title] => Alumnus' Dinner Coming Soon
[post_parent] => 0
[post_date] => 2012-01-31 12:00:51
)
Echoing the result from calling json_encode() on this object results in the following:
{
"ID": "12981",
"post_title": null,
"post_parent": "0",
"post_date": "2012-01-31 12:00:51"
}
I'm assuming that something with the single quote is causing json_encode to choke, but I don't know what format is needed to escape that. Any ideas?
EDIT: Fixed mismatch in code examples. I'm running PHP version 5.3.8
EDIT2: Directly after encoding the object, I did this:
echo json_last_error() == JSON_ERROR_UTF8;
This printed 1, which means that the following error occurred: "Malformed UTF-8 characters, possibly incorrectly encoded". json_last_error()
EDIT3: Calling utf8_decode() on the post title resulted in the following: "Alumnus? Dinner Coming Soon". This data is being pulled from a MySQL database - the post title in particular is a text field, UTF-8 encoded. Maybe this single-quote is improperly encoded? The thing is, I have a SQL GUI app, and it appears correctly in that.
You need to set the connection encoding before executing queries. How this is done depends on the API you are using to connect:
call mysql_set_charset("utf8") if you use the old, deprecated API.
call mysqli_set_charset("utf8") if you use mysqli
add the charset parameter to the connection string if you use PDO and PHP >= 5.3.6. In earlier versions you need to execute SET NAMES utf8.
When you obtain data from MySQL any text will be encoded in "client encoding", which is likely windows-1252 if you don't configure it otherwise. The character that is causing your problem is the "curly quote", seen as 92 in the hex dump, which confirms that the mysql client is encoding text in windows-1252.
Another thing you might consider is pass all text through utf8_encode, but in this case it wouldn't produce the correct result. PHP's utf8_encode converts iso-8859-1-encoded text. In this encoding \x92 is a non-printable control character, which would be converted into a non-printable control character in utf-8. You could use str_replace("\x92", "'", $input) to fix the problem for this particular character, but if there's any chance there will be any other non-ascii characters in the database you'll want to have the client use UTF-8.
What I've had to do in the past to json_encode on text with utf8 characters is
json_encode( utf8_encode( $s ) );
and in some cases
json_encode( htmlspecialchars( utf8_encode( $s ) ) );
the utf8_encode() to handle special characters (note, that's Encode, not Decode)
the htmlspecialchars() depending on how you mean to use the JSON string, you may be able to leave this out
and finally, json_encode() to get your JSON packet.
Since you want to json_encode an object, you would need to call utf8_encode() on each text part first, or write a simple recursive utf8_encode(). For your example case, this would do:
function myEncode($o) {
$o->title = utf8_encode($o->title);
return json_encode($o);
}
I would like to refer you about this issue,
on link
I suggest you use a json_encode wrapper like this :
function safe_json_encode($value){
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$encoded = json_encode($value, JSON_PRETTY_PRINT);
} else {
$encoded = json_encode($value);
}
switch (json_last_error()) {
case JSON_ERROR_NONE:
return $encoded;
case JSON_ERROR_DEPTH:
return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
case JSON_ERROR_STATE_MISMATCH:
return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
case JSON_ERROR_CTRL_CHAR:
return 'Unexpected control character found';
case JSON_ERROR_SYNTAX:
return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
case JSON_ERROR_UTF8:
$clean = utf8ize($value);
return safe_json_encode($clean);
default:
return 'Unknown error'; // or trigger_error() or throw new Exception()
}
}
function utf8ize($mixed) {
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = utf8ize($value);
}
} else if (is_string ($mixed)) {
return utf8_encode($mixed);
}
return $mixed;
}
And after define these function you can use it direct,
echo safe_json_encode($response);
i was having the same issue while JSON encoding a php array from an ODBC query results, my Server's OBC is configured with 'en_US.819', is a production server so there is no way i can even touch that!!.
when i tried:
echo json_encode($GLOBALS['response'], true);
Where 'respose' is an array with the results, it works as intended as long no bizarre char is present, if so, json_encode fails returning empty.
The solution?.... UTF encode results while fetching the rows from query:
$result = odbc_exec($conn, $sql_query);
$response = array();
while( $row = odbc_fetch_array($result) ) {
$json['pers_identificador'] = $row['pers_identificador'];
$json['nombre_persona'] = utf8_encode( $row['nombre_persona'] );
$json['nombre_1'] = utf8_encode($row['nombre_1'] );
$json['nombre_2'] = utf8_encode($row['nombre_2'] );
array_push($response, $json);
}
Now json_encode works!!!, the resulting string is something like this:
{"page_id":300,"max_rows":"100","cant_rows":"12897","datos":
[{"pers_identificador":"301","cedula":"15250068","interno_1":"178202","interno_2":"","nombre_persona":"JOSE JUAN PANDOLFO ZAGORODKO","nombre_1":"JOSE","nombre_2":"JUAN",....
That fixed my issue.
You can try to set the charset in the database config:
'charset' => 'utf8',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
)
I have a problem where I thought it was easy to Google but it seems to be not that easy. Ok, here is my problem:
I have to read a CSV file which has a bad and different encoding. I'm not able to correct the CSV file before hand, so I have to handle it in my application. So the CSV file could have the following-encodings:
'Ü5' and 'Möbelmarkt' in the same file.
If I decode (utf8_decode) the right one is correct and the left (which was correct) is wrong. When I try to find out the encoding (mb_detect_encoding) i always get the answer that this is UTF-8.
I still tried the following solutions:
public function convert( $str ) {
return iconv( "Windows-1252", "UTF-8", $str );
}
and
private function getUmlauteArray() {
return array( 'ü'=>'ü', 'ä'=>'ä', 'ö'=>'ö', 'Ö'=>'Ö', 'ß'=>'ß', 'à '=>'à', 'á'=>'á', 'â'=>'â', 'ã'=>'ã', 'ù'=>'ù', 'ú'=>'ú', 'û'=>'û', 'Ù'=>'Ù', 'Ú'=>'Ú', 'Û'=>'Û', 'Ãœ'=>'Ü', 'ò'=>'ò', 'ó'=>'ó', 'ô'=>'ô', 'è'=>'è', 'é'=>'é', 'ê'=>'ê', 'ë'=>'ë', 'À'=>'À', 'Ã'=>'Á', 'Â'=>'Â', 'Ã'=>'Ã', 'Ä'=>'Ä', 'Ã…'=>'Å', 'Ç'=>'Ç', 'È'=>'È', 'É'=>'É', 'Ê'=>'Ê', 'Ë'=>'Ë', 'ÃŒ'=>'Ì', 'Ã'=>'Í', 'ÃŽ'=>'Î', 'Ã'=>'Ï', 'Ñ'=>'Ñ', 'Ã’'=>'Ò', 'Ó'=>'Ó', 'Ô'=>'Ô', 'Õ'=>'Õ', 'Ø'=>'Ø', 'Ã¥'=>'å', 'æ'=>'æ', 'ç'=>'ç', 'ì'=>'ì', 'Ã'=>'í', 'î'=>'î', 'ï'=>'ï', 'ð'=>'ð', 'ñ'=>'ñ', 'õ'=>'õ', 'ø'=>'ø', 'ý'=>'ý', 'ÿ'=>'ÿ', '€'=>'€' );
}
public function fixeUmlaute($string) {
$umlaute = $this->getUmlauteArray();
foreach ($umlaute as $key => $value){
$value = str_replace($key, $value, $string);
}
return $string;
}
and
function valid_utf8( $string ){
return !((bool)preg_match('~[\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF\xC0\xC1]~ms',$string));
}
That are all solutions I found with a Google search to change the encoding...(perhaps this "collection" helps anybody else...) So, how can I really detect the wrong characters or where is it my mistake?
Can anybody give me a hint?
Greetz
V
There is a nice PHP class that can help you with that: https://github.com/neitanod/forceutf8
It will convert any charset to UTF8, and handle the detection for you. Hope it helps.
I have a stdClass object called $post that, when dumped via print_r(), returns the following:
stdClass Object (
[ID] => 12981
[post_title] => Alumnus' Dinner Coming Soon
[post_parent] => 0
[post_date] => 2012-01-31 12:00:51
)
Echoing the result from calling json_encode() on this object results in the following:
{
"ID": "12981",
"post_title": null,
"post_parent": "0",
"post_date": "2012-01-31 12:00:51"
}
I'm assuming that something with the single quote is causing json_encode to choke, but I don't know what format is needed to escape that. Any ideas?
EDIT: Fixed mismatch in code examples. I'm running PHP version 5.3.8
EDIT2: Directly after encoding the object, I did this:
echo json_last_error() == JSON_ERROR_UTF8;
This printed 1, which means that the following error occurred: "Malformed UTF-8 characters, possibly incorrectly encoded". json_last_error()
EDIT3: Calling utf8_decode() on the post title resulted in the following: "Alumnus? Dinner Coming Soon". This data is being pulled from a MySQL database - the post title in particular is a text field, UTF-8 encoded. Maybe this single-quote is improperly encoded? The thing is, I have a SQL GUI app, and it appears correctly in that.
You need to set the connection encoding before executing queries. How this is done depends on the API you are using to connect:
call mysql_set_charset("utf8") if you use the old, deprecated API.
call mysqli_set_charset("utf8") if you use mysqli
add the charset parameter to the connection string if you use PDO and PHP >= 5.3.6. In earlier versions you need to execute SET NAMES utf8.
When you obtain data from MySQL any text will be encoded in "client encoding", which is likely windows-1252 if you don't configure it otherwise. The character that is causing your problem is the "curly quote", seen as 92 in the hex dump, which confirms that the mysql client is encoding text in windows-1252.
Another thing you might consider is pass all text through utf8_encode, but in this case it wouldn't produce the correct result. PHP's utf8_encode converts iso-8859-1-encoded text. In this encoding \x92 is a non-printable control character, which would be converted into a non-printable control character in utf-8. You could use str_replace("\x92", "'", $input) to fix the problem for this particular character, but if there's any chance there will be any other non-ascii characters in the database you'll want to have the client use UTF-8.
What I've had to do in the past to json_encode on text with utf8 characters is
json_encode( utf8_encode( $s ) );
and in some cases
json_encode( htmlspecialchars( utf8_encode( $s ) ) );
the utf8_encode() to handle special characters (note, that's Encode, not Decode)
the htmlspecialchars() depending on how you mean to use the JSON string, you may be able to leave this out
and finally, json_encode() to get your JSON packet.
Since you want to json_encode an object, you would need to call utf8_encode() on each text part first, or write a simple recursive utf8_encode(). For your example case, this would do:
function myEncode($o) {
$o->title = utf8_encode($o->title);
return json_encode($o);
}
I would like to refer you about this issue,
on link
I suggest you use a json_encode wrapper like this :
function safe_json_encode($value){
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$encoded = json_encode($value, JSON_PRETTY_PRINT);
} else {
$encoded = json_encode($value);
}
switch (json_last_error()) {
case JSON_ERROR_NONE:
return $encoded;
case JSON_ERROR_DEPTH:
return 'Maximum stack depth exceeded'; // or trigger_error() or throw new Exception()
case JSON_ERROR_STATE_MISMATCH:
return 'Underflow or the modes mismatch'; // or trigger_error() or throw new Exception()
case JSON_ERROR_CTRL_CHAR:
return 'Unexpected control character found';
case JSON_ERROR_SYNTAX:
return 'Syntax error, malformed JSON'; // or trigger_error() or throw new Exception()
case JSON_ERROR_UTF8:
$clean = utf8ize($value);
return safe_json_encode($clean);
default:
return 'Unknown error'; // or trigger_error() or throw new Exception()
}
}
function utf8ize($mixed) {
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = utf8ize($value);
}
} else if (is_string ($mixed)) {
return utf8_encode($mixed);
}
return $mixed;
}
And after define these function you can use it direct,
echo safe_json_encode($response);
i was having the same issue while JSON encoding a php array from an ODBC query results, my Server's OBC is configured with 'en_US.819', is a production server so there is no way i can even touch that!!.
when i tried:
echo json_encode($GLOBALS['response'], true);
Where 'respose' is an array with the results, it works as intended as long no bizarre char is present, if so, json_encode fails returning empty.
The solution?.... UTF encode results while fetching the rows from query:
$result = odbc_exec($conn, $sql_query);
$response = array();
while( $row = odbc_fetch_array($result) ) {
$json['pers_identificador'] = $row['pers_identificador'];
$json['nombre_persona'] = utf8_encode( $row['nombre_persona'] );
$json['nombre_1'] = utf8_encode($row['nombre_1'] );
$json['nombre_2'] = utf8_encode($row['nombre_2'] );
array_push($response, $json);
}
Now json_encode works!!!, the resulting string is something like this:
{"page_id":300,"max_rows":"100","cant_rows":"12897","datos":
[{"pers_identificador":"301","cedula":"15250068","interno_1":"178202","interno_2":"","nombre_persona":"JOSE JUAN PANDOLFO ZAGORODKO","nombre_1":"JOSE","nombre_2":"JUAN",....
That fixed my issue.
You can try to set the charset in the database config:
'charset' => 'utf8',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
)