Berk Akademi
Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

PHP "Malformed UTF-8 characters, possibly incorrectly encoded" Hatası Nasıl Çözülür?

php-malformed-utf-8-hatasi-nasil-cozulur
Bu yazıda neler var?
  1. Hata ne anlama gelir: json_encode() neden geçersiz UTF-8 veriyi kabul etmez?
  2. json_encode() ve hata fonksiyonlarıyla sorunu küçük bir örnekte gör
  3. Kaynağa göre kontrol listesi: form, dosya, veritabanı ve API
  4. Hata mesajından kök nedene giden teşhis ağacı
  5. Düzeltmeden sonra veriyi kaybetmeden JSON üret
  6. Sık Sorulan Sorular

PHP "Malformed UTF-8 characters, possibly incorrectly encoded" hatası, json_encode() içine verilen dizi, nesne veya iç içe yapının en az bir metin değerinde geçerli UTF-8 byte dizisi bulunmadığında görülür. Sorunu çözmek için bozuk alanı kaynağında bulup kodlamasını doğrulamak, kaynak kodlama biliniyorsa veriyi UTF-8'e dönüştürmek ve dönüşümün veri kaybı oluşturup oluşturmadığını kontrol etmek gerekir.

Hata çoğu zaman JSON yapısından değil, form, dosya, veritabanı veya API'den gelen metnin byte içeriğinden kaynaklanır. JSON_UNESCAPED_UNICODE Türkçe karakterleri JSON içinde okunabilir tutabilir, ancak geçersiz byte dizisini onarmaz.

Hata ne anlama gelir: json_encode() neden geçersiz UTF-8 veriyi kabul etmez?

json_encode(), bir dizi veya nesneyi JSON'a dönüştürürken içindeki metin değerlerini de işler. PHP'nin resmî json_encode() belgelerinde tüm string verilerinin UTF-8 kodlu olması gerektiği belirtilir. Bu nedenle tek bir alan bozuksa, dizinin anahtarları ve yapısı doğru görünse bile JSON üretimi başarısız olabilir.

Burada iki farklı katmanı ayırmak önemlidir: JSON, verinin nasıl temsil edildiğini belirleyen çıktı formatıdır; UTF-8 ise metnin byte düzeyindeki kodlamasıdır. Form alanı, dosya içeriği, veritabanı sonucu veya API yanıtı geçersiz byte içeriyorsa kök neden çoğunlukla JSON yapısında değil, verinin kaynağında ya da taşınma biçimindedir.

JSON_UNESCAPED_UNICODE yalnızca geçerli çok baytlı Unicode karakterlerinin JSON içinde doğrudan gösterilmesini sağlar. Böylece Türkçe karakterler uXXXX biçimi yerine okunabilir şekilde kalabilir. Ancak xC3x28 gibi bozuk bir byte dizisini düzeltmez, eksik byte'ları tamamlamaz ve kaynağın kodlamasını değiştirmez. Bu seçeneği bir onarım yöntemi değil, geçerli verinin çıktı biçimini belirleyen bir tercih olarak düşünmelisin.

json_encode() ve hata fonksiyonlarıyla sorunu küçük bir örnekte gör

json_encode() ve hata fonksiyonlarıyla sorunu küçük bir örnekte gör

Önce geçerli Türkçe metni, ardından aynı dizinin bozuk byte içeren hâlini kodlayabilirsin. Aşağıdaki örnekte xC3x28 bilerek geçersiz bir UTF-8 dizisi olarak kullanılır. Çalışma tamamlandı ise geçerli veriyle karşılaştırma yapmak için eklenir.

Varsayılan akışta dönüş değerini ve son hata durumunu birlikte kontrol et. PHP'nin json_last_error() belgeleri, hata kodunu ve hata açıklamasını incelemek için json_last_error() ile json_last_error_msg() işlevlerini kullanabileceğini belirtir.

<?php
$veriler = [
    'mesaj' => 'Çalışma tamamlandı',
    'bozuk' => "xC3x28",
];

$gecerliJson = json_encode(
    $veriler['mesaj'],
    JSON_UNESCAPED_UNICODE
);

var_dump($gecerliJson);
var_dump(json_last_error(), json_last_error_msg());

$hataliJson = json_encode(
    $veriler,
    JSON_UNESCAPED_UNICODE
);

var_dump($hataliJson);
var_dump(json_last_error(), json_last_error_msg());

try {
    $json = json_encode(
        $veriler,
        JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR
    );

    echo $json, PHP_EOL;
} catch (JsonException $e) {
    echo 'Yakalanan hata: ', $e->getMessage(), PHP_EOL;
}

Beklenen sonuçlar:

  • Geçerli değer: "Çalışma tamamlandı" şeklinde JSON üretilir ve son hata durumu JSON_ERROR_NONE ile eşleşir.
  • Bozuk değer: json_encode() dönüşü false olur. json_last_error() sonucu JSON_ERROR_UTF8, json_last_error_msg() sonucu ise Malformed UTF-8 characters, possibly incorrectly encoded olur.
  • Exception akışı: JSON_THROW_ON_ERROR kullanıldığında JsonException yakalanır ve catch bloğundaki hata mesajı yazdırılır.

Örnekte JSON_UNESCAPED_UNICODE geçerli Türkçe metnin karakterlerini korur, fakat xC3x28 değerini onarmaz. Hata devam ediyorsa çözüm, farklı bir JSON seçeneği eklemekten önce bozuk metnin hangi alandan geldiğini bulmaktır.

Kaynağa göre kontrol listesi: form, dosya, veritabanı ve API

Kaynağa göre kontrol listesi: form, dosya, veritabanı ve API

JSON üretmeden önce verinin hangi kaynaktan geldiğini ayırmak teşhisi kolaylaştırır. Her kaynağın ham değerini incele, UTF-8 geçerliliğini denetle ve yalnızca kaynak kodlama gerçekten biliniyorsa dönüşüm uygula.

Kaynak İlk kontrol mb_check_encoding() denetimi Kaynak kodlama biliniyorsa dönüşüm Veri kaybı riski
Form $_POST veya $_GET içindeki alınan alanı ve alanın türünü kontrol et. Alanı tek başına mb_check_encoding($value, 'UTF-8') ile denetle. Kaynak biliniyorsa mb_convert_encoding($value, 'UTF-8', $sourceEncoding) uygula ve yeniden denetle. Yanlış kaynak seçimi karakterleri değiştirebilir; daha önce kaybolan veri geri gelmez.
Dosya file_get_contents() ile ham byte içeriğini, dosya adı, uzantı ve dosya bilgisini birlikte incele. Okunan içeriği mb_check_encoding($value, 'UTF-8') ile kontrol et. Dosyanın üretildiği kodlama biliniyorsa uygun mb_convert_encoding() dönüşümünü yap, ardından tekrar kontrol et. Yanlış varsayım, özel karakterlerin değişmesine veya içeriğin eksilmesine yol açabilir.
Veritabanı Saklanan değeri ve verinin eklenip okunurken izlediği akışı incele. Okunan alan için mb_check_encoding($value, 'UTF-8') sonucunu kontrol et. Kaynak kodlama kesin olarak biliniyorsa değeri UTF-8'e dönüştür ve yeniden denetle. Veritabanına yazılmadan önce bozulmuş karakterler dönüşümle geri getirilemez.
API Ham yanıt gövdesini ve Content-Type içindeki mevcut kodlama bilgisini kontrol et. Yanıt gövdesini mb_check_encoding($value, 'UTF-8') ile denetle. Yanıtın kaynak kodlaması biliniyorsa mb_convert_encoding() kullan, sonra tekrar kontrol et. Kaynak bilinmiyorsa rastgele kodlama seçmek veri değişimine neden olabilir.

mb_check_encoding(), verilen değerin belirtilen kodlamaya uygunluğunu true veya false olarak bildirir. mb_convert_encoding() ise bilinen bir kaynak kodlamadan hedef kodlamaya dönüşüm yapar. Dönüşüm, daha önce bozulmuş veya kaybolmuş byte'ları onaramaz. Bu nedenle dönüşüm sonrasında hem UTF-8 geçerliliğini hem de metnin anlamını kontrol et.

Hata mesajından kök nedene giden teşhis ağacı

Teşhisi şu sırayla ilerlet: veriyi kontrol et, hatalı alanı izole et, kaynağı belirle, UTF-8 geçerliliğini denetle, gerekiyorsa dönüştür ve JSON üretimini yeniden dene.

  1. Veriyi kontrol et: json_encode() içine gönderilen dizi veya nesnedeki tüm string alanlarını belirle.
  2. Başarısız alanı izole et: Birden fazla alan varsa değerleri tek tek tara. İç içe dizilerde alt alanları da ayrı incele. Tek bir alan bozukken tüm yapıyı rastgele dönüştürme.
  3. Kaynağı belirle:
    • Form: Hatalı alanın ham gönderim değerine bak.
    • Dosya: Dosya içeriğini ve dosya bilgisini birlikte incele.
    • Veritabanı: Saklanan değeri ve değerin sisteme giriş yolunu takip et.
    • API: Ham yanıt gövdesini ve içerik bilgisini kontrol et.
  4. UTF-8 geçerliliğini denetle: Şüpheli her string için mb_check_encoding($value, 'UTF-8') kullan.
  5. Yalnızca kaynak kodlama biliniyorsa dönüştür: Uygun $sourceEncoding değeriyle mb_convert_encoding() çağır.
  6. Dönüşümden sonra yeniden denetle: Sonucun geçerli UTF-8 olduğunu ve karakterlerin beklenen anlamı koruduğunu kontrol et.
  7. Yeniden JSON üret: Sorunlu alan düzeltildikten sonra json_encode() çağrısını tekrar çalıştır.

mb_check_encoding() başarılı olduğu hâlde JSON üretimi başarısızsa başka bir iç içe alanı veya ham byte içeren değeri inceleme adımına dön. Hata yakalanan tek alanı düzeltmek, bütün veri yapısını körlemesine dönüştürmekten daha güvenli bir yaklaşımdır.

Düzeltmeden sonra veriyi kaybetmeden JSON üret

Güvenli üretim akışı, hatayı susturmakla değil verinin gerçekten geçerli UTF-8 olduğundan emin olmakla başlar. Önce özgün değeri koru, kaynağın kodlamasını belirle, gerekiyorsa tek bir dönüşüm uygula ve sonucu yeniden doğrula. json_encode() için tüm dizgelerin UTF-8 olması gerekir; JSON_THROW_ON_ERROR kullanıldığında kodlama hatası bir JsonException olarak yakalanabilir.

  • Özgün değeri dönüşümden önce koru.
  • mb_check_encoding($deger, 'UTF-8') ile mevcut değeri denetle.
  • Kaynak kodlama biliniyorsa yalnızca bir kez UTF-8'e dönüştür.
  • Dönüşümden sonra mb_check_encoding() ile yeniden doğrula.
  • JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR ile JSON üretmeyi dene ve hatayı yakala.

Kaynak kodlama bilinmiyorsa rastgele bir kodlama adı seçerek dönüşüm yapmak, Türkçe karakterleri değiştirebilir veya veri kaybına yol açabilir. Örneğin kaynak gerçekten Windows-1252 ise mb_convert_encoding($deger, 'UTF-8', 'Windows-1252') kullanılabilir; ancak bu kodlama yalnızca verinin gerçek kaynağı buysa doğrudur. mb_convert_encoding() kaynak ve hedef kodlamayı açıkça belirtmeye izin verir.

<?php
$gecerli = "İzmir'de ş, ğ, ü, ö, ç.";
$bozuk = "İzmir xC3x28";

echo json_encode($gecerli, JSON_UNESCAPED_UNICODE) . PHP_EOL;

$sonuc = json_encode($bozuk, JSON_UNESCAPED_UNICODE);
echo ($sonuc === false ? "false" : $sonuc) . PHP_EOL;
echo (json_last_error() === JSON_ERROR_UTF8 ? "JSON_ERROR_UTF8" : "başka hata");
echo " / " . json_last_error_msg() . PHP_EOL;

try {
    json_encode($bozuk, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo "Yakalandı: " . $e->getMessage() . PHP_EOL;
}

Burada ilk değer geçerli Türkçe karakterler içerdiği için JSON'a dönüştürülür. xC3x28 ise geçersiz bir UTF-8 byte dizisini simüle eder. Hatasız çağrıda json_last_error() ve json_last_error_msg() ile durum okunabilir; JSON_THROW_ON_ERROR kullanılan çağrıda ise istisna yakalanır.

Beklenen çıktı:

"İzmir'de ş, ğ, ü, ö, ç."
false
JSON_ERROR_UTF8 / Malformed UTF-8 characters, possibly incorrectly encoded
Yakalandı: Malformed UTF-8 characters, possibly incorrectly encoded

JSON_UNESCAPED_UNICODE yalnızca geçerli Unicode karakterlerinin JSON içinde doğrudan görünmesini sağlar. Bozuk byte'ı onarmaz. JSON üretiminin başarılı olması da dönüşümün anlamı koruduğunu tek başına kanıtlamaz. Özellikle ad, açıklama, adres ve kullanıcı mesajı gibi kritik alanları dönüşüm öncesi ve sonrası ayrıca incele. Üretim reçetesi şudur: doğrula, kaynağı belirle, gerekiyorsa dönüştür, yeniden doğrula, JSON üret.

Sık Sorulan Sorular

JSON_UNESCAPED_UNICODE bu PHP hatasını neden düzeltmez?

Bu seçenek yalnızca geçerli çok baytlı karakterlerin JSON içinde uXXXX biçimi yerine karakter olarak yazılmasını sağlar. Geçersiz UTF-8 byte'larını değiştirmez veya onarmaz.

mb_check_encoding() false döndürürse hangi kodlama dönüşümü uygulanmalı?

Tek bir evrensel dönüşüm yoktur. Verinin gerçek kaynak kodlamasını belirleyip o kodlamadan UTF-8'e dönüşüm yapmalısın. Kaynak bilinmiyorsa rastgele dönüşüm uygulamak yerine verinin geldiği katmanı incelemek daha güvenlidir.

Veritabanından gelen bir değerin geçersiz UTF-8 içerdiği nasıl anlaşılır?

PHP değişkenine alınan değeri mb_check_encoding($deger, 'UTF-8') ile denetleyebilirsin. Sonuç false ise değer, PHP'nin beklediği UTF-8 dizisi olarak doğrulanmamıştır.

json_last_error() ile JSON_THROW_ON_ERROR arasında ne fark vardır?

json_last_error() ve json_last_error_msg(), hata oluşturan çağrıdan sonra hata durumunu okumaya yarar. JSON_THROW_ON_ERROR ise hata meydana geldiğinde JsonException fırlatır ve bu istisna try-catch ile ele alınır.

Geçerli JSON üretmek için amaç yalnızca hata mesajını kaldırmak değil, dönüşümün veriyi koruduğunu denetleyerek güvenilir bir çıktı oluşturmaktır.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara