فك تشفير PHP وترميز json بأحرف Unicode
-
29-10-2019 - |
سؤال
لدي بعض ملفات json التي أحتاج إلى فك تشفيرها وتعديلها ثم تشفيرها دون العبث بأي أحرف.
إذا كان لدي حرف Unicode في سلسلة json فلن يتم فك تشفيره.لست متأكدًا من السبب حيث أن json.org يقول أن السلسلة يمكن أن تحتوي على: any-Unicode-character- except-"-or-\-or- control-character
.لكنها لا تعمل في بايثون أيضًا.
{"Tag":"Odómetro"}
يمكنني استخدام utf8_encode الذي سيسمح بفك تشفير السلسلة باستخدام json_decode، ولكن الحرف يتشوه إلى شيء آخر.هذه هي النتيجة من print_r لمصفوفة النتائج.شخصيتان.
[Tag] => Odómetro
عندما أقوم بتشفير المصفوفة مرة أخرى، أفلت الحرف إلى ascii، وهو صحيح وفقًا لمواصفات json:
"Tag"=>"Od\u00f3metro"
هل هناك طريقة ما يمكنني من خلالها الهروب من هذا؟لا يوفر json_encode مثل هذا الخيار، ويبدو أن utf8_encode لا يعمل أيضًا.
يحرر أرى أن هناك خيار unescaped_unicode لـ json_encode.ومع ذلك فهو لا يعمل كما هو متوقع.يا إلهي، إنه موجود فقط على php 5.4.سيتعين علي استخدام بعض التعبيرات العادية لأن لدي 5.3 فقط.
$json = json_encode($array, JSON_UNESCAPED_UNICODE);
Warning: json_encode() expects parameter 2 to be long, string ...
المحلول
بالنظر إلى كل ما قلته، يبدو أنه الأصلي Odómetro
السلسلة التي تتعامل معها مشفرة بـ ISO 8859-1، وليس UTF-8.
لهذا السبب أعتقد ذلك:
json_encode
أنتجت مخرجات قابلة للتحليل بعد تشغيل سلسلة الإدخال من خلالهاutf8_encode
, ، والذي يتحول من ISO 8859-1 إلى UTF-8.- لقد قلت أنك حصلت على مخرجات "مشوهة" عند الاستخدام
print_r
بعد القيامutf8_encode
, ، لكن المخرجات المشوهة التي حصلت عليها هي في الواقع بالضبط ما سيحدث عند محاولة تحليل نص UTF-8 كـ ISO 8859-1 (ó هو\x63\xb3
في UTF-8، ولكن هذا التسلسلó
في ISO 8859-1. - لك
htmlentities
نجح حل الاختراق.htmlentities
يحتاج إلى معرفة ما هو ترميز سلسلة الإدخال للعمل بشكل صحيح.إذا لم تحدد واحدًا، فإنه يفترض ISO 8859-1.(html_entity_decode
, ، من المربك أن الإعداد الافتراضي هو UTF-8، لذلك كان لطريقتك تأثير التحويل من ISO 8859-1 إلى UTF-8.) - لقد قلت إن لديك نفس المشكلة في بايثون، والتي يبدو أنها تستبعد PHP من كونها المشكلة.
سوف يستخدم PHP \uXXXX
الهروب، ولكن كما لاحظت، هذا هو JSON صالح.
لذا، يبدو أنك بحاجة إلى تهيئة اتصالك بـ Postgres بحيث يمنحك سلاسل UTF-8.يشير دليل PHP إلى أنك ستفعل ذلك عن طريق إلحاق options='--client_encoding=UTF8'
إلى سلسلة الاتصال.هناك أيضًا احتمال أن تكون البيانات المخزنة حاليًا في قاعدة البيانات بترميز خاطئ.(يمكنك ببساطة استخدام utf8_encode
, ، ولكن هذا لن يدعم سوى الأحرف التي تشكل جزءًا من ISO 8859-1).
أخيرًا، كما تمت الإشارة إلى إجابة أخرى، فأنت بحاجة إلى التأكد من أنك تعلن عن مجموعة الأحرف المناسبة، باستخدام رأس HTTP أو غير ذلك (بالطبع، ربما كانت هذه المشكلة بالذات مجرد قطعة أثرية من البيئة التي قمت فيها بعملك print_r
اختبارات).
نصائح أخرى
لقد وجدت الطريقة التالية لإصلاح هذه المشكلة ...آمل أن يكون هذا يمكن أن تساعدك.
json_encode($data,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
JSON_UNESCAPED_UNICODE
تمت إضافته في PHP 5.4 لذا يبدو أنك بحاجة إلى ترقية إصدار PHP الخاص بك للاستفادة منه.5.4 لم يصدر بعد!:(
هناك 5.4 مرشح إطلاق ألفا على ضمان الجودة على الرغم من أنك إذا كنت تريد اللعب على جهاز التطوير الخاص بك.
طريقة مخترقة للقيام بـ JSON_UNESCAPED_UNICODE في PHP 5.3.محبط حقًا بسبب دعم PHP json.ربما هذا سوف يساعد شخص آخر.
$array = some_json();
// Encode all string children in the array to html entities.
array_walk_recursive($array, function(&$item, $key) {
if(is_string($item)) {
$item = htmlentities($item);
}
});
$json = json_encode($array);
// Decode the html entities and end up with unicode again.
$json = html_entity_decode($rson);
حاول ضبط utf-8
الترميز في صفحتك:
header('content-type:text/html;charset=utf-8');
هذا يعمل بالنسبة لي:
$arr = array('tag' => 'Odómetro');
$encoded = json_encode($arr);
$decoded = json_decode($encoded);
echo $decoded->{'tag'};
$json = array('tag' => 'Odómetro'); // Original array
$json = json_encode($json); // {"Tag":"Od\u00f3metro"}
$json = json_decode($json); // Od\u00f3metro becomes Odómetro
echo $json->{'tag'}; // Odómetro
echo utf8_decode($json->{'tag'}); // Odómetro
لقد كنت قريبًا، فقط استخدم utf8_decode.
جرب استخدام:
utf8_decode() and utf8_encode
لتشفير مصفوفة تحتوي على أحرف خاصة، من ISO 8859-1 إلى UTF8.(إذا لم يكن utf8_encode وutf8_decode هو ما يناسبك، فقد يكون هذا أحد الخيارات)
يجب تحويل كل ما هو موجود في ISO-8859-1 إلى UTF8:
$utf8 = utf8_encode('이 감사의 마음을 전합니다!'); //contains UTF8 & ISO 8859-1 characters;
$iso88591 = mb_convert_encoding($utf8, 'ISO-8859-1', 'UTF-8');
$data = $iso88591;
يجب أن يعمل التشفير بعد ذلك:
$encoded_data = json_encode($data);