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

Python response.json JSONDecodeError hatası nasıl çözülür?

python-response-json-jsondecodeerror-hatasi
Bu yazıda neler var?
  1. JSONDecodeError neyi anlatır ve neyi anlatmaz?
  2. Teşhis sırası: status code'dan gövde içeriğine ilerleyin
  3. Belirti, olası neden, kontrol ve çözüm: tek teşhis tablosu
  4. Postman'da çalışan istek Python'da neden farklı yanıt döndürür?
  5. Çalışabilir mini istemciyle ağ, HTTP ve JSON hatalarını ayırın
  6. Sık Sorulan Sorular

Python response.json JSONDecodeError hatası, response.json() çağrısının HTTP yanıt gövdesini JSON olarak ayrıştıramadığını gösterir. En sık nedenler gövdenin boş olması, HTML veya düz metin dönmesi ya da JSON sözdiziminin geçersiz olmasıdır. Bu hata tek başına ağ bağlantısının kurulamadığını veya kimlik doğrulamanın başarısız olduğunu kanıtlamaz; ağ, HTTP durum kodu ve JSON ayrıştırma kontrolleri ayrı yapılmalıdır.

JSONDecodeError neyi anlatır ve neyi anlatmaz?

response.json(), requests kütüphanesinin aldığı yanıt gövdesini JSON olarak okuyup Python nesnesine dönüştürmeye çalışır. Gövde geçerli bir JSON içeriyorsa sözlük, liste, metin veya sayı gibi bir Python değeri dönebilir. Gövde JSON değilse Requests, requests.exceptions.JSONDecodeError hatasını oluşturur. Boş yanıt, HTML hata sayfası, düz metin mesajı ve virgül ya da tırnak hatası içeren içerikler bu duruma örnek olabilir.

Ancak bu hata, isteğin sunucuya hiç ulaşmadığını söylemez. Ağ bağlantısı kurulamadığında veya istek zaman aşımına uğradığında genellikle ConnectionError ya da Timeout gibi farklı hatalarla karşılaşılır. Benzer şekilde kimlik doğrulama ve yetki sorunları, yanıtın status_code değeri ve gövdesi incelenerek ayrıca değerlendirilmelidir. HTTP yanıtı alınmış olsa bile gövdenin JSON olması garanti edilmez.

Bir başka önemli ayrım da HTTP durum kodu ile JSON ayrıştırma sonucunun farklı şeyler olmasıdır. Örneğin başarılı görünen bir HTTP durum kodu, yanıt gövdesinin geçerli JSON olduğunu tek başına kanıtlamaz. Tersine, başarısız bir HTTP yanıtı da JSON biçiminde hata ayrıntıları içerebilir ve response.json() bu içeriği ayrıştırabilir. Bu nedenle yalnızca try-except eklemek yerine önce alınan yanıtın ne olduğunu teşhis etmek gerekir.

Bu ayrımları takip etmekte zorlanıyorsan, temel Python sözdizimi, hata yönetimi ve veri yapıları konusundaki açığını görmek için Python bilgi testlerinden yararlanabilirsin. Bu testler JSONDecodeError sorununu doğrudan çözmez; yalnızca teşhis sırasında ihtiyaç duyduğun Python temellerini değerlendirmene yardımcı olur.

Teşhis sırası: status code'dan gövde içeriğine ilerleyin

Teşhis sırası: status code'dan gövde içeriğine ilerleyin

Hatanın kaynağını bulmak için response.json() çağrısını hemen yapmak yerine aşağıdaki sırayı izleyin. Böylece ağ sorunu, HTTP yanıtı ve JSON biçimi birbirine karışmaz.

  1. response.status_code değerini kontrol edin. Yanıtın beklediğiniz HTTP durum kodunu taşıyıp taşımadığını inceleyin. İstemci veya sunucu kaynaklı bir HTTP problemi varsa bunu JSON ayrıştırma probleminden ayrı ele alın. Gerekirse response.raise_for_status() ile HTTP hatasını görünür hâle getirebilirsiniz.
  2. Content-Type başlığına bakın. response.headers.get("Content-Type") ifadesi, sunucunun gövdeyi hangi türde gönderdiğine dair bir sinyal verir. application/json görülmesi olumlu bir işarettir; fakat bu başlık JSON sözdiziminin gerçekten geçerli olduğunu tek başına kanıtlamaz.
  3. response.text ile okunabilir gövdeyi inceleyin. print(repr(response.text)) kullanarak HTML etiketlerini, düz metin hata mesajını veya beklenmeyen bir yönlendirme içeriğini görebilirsiniz. Requests, bu özelliği metin olarak sunarken yanıt kodlamasını HTTP başlıklarına göre belirler.
  4. response.content ile ham byte verisini değerlendirin. Özellikle görünmeyen karakterlerden veya kodlama sorunlarından şüpheleniyorsanız repr(response.content) ya da içeriğin ilk byte'larını inceleyin. response.content yanıt gövdesini byte olarak verir.
  5. Gövdenin boş olup olmadığını kontrol edin. if not response.content.strip(): kontrolü, hem tamamen boş hem de yalnızca boşluk karakterlerinden oluşan yanıtları yakalar. Böyle bir durumda response.json() çağırmak yerine boş gövdeyi ayrı bir durum olarak ele alın.
  6. JSON ayrıştırmayı dar bir try-except sınırında deneyin. Ön kontrollerden sonra yalnızca response.json() satırını sarmalayın:
try:
    veri = response.json()
except requests.exceptions.JSONDecodeError:
    print("Yanıt gövdesi geçerli JSON değil:", repr(response.text))

Bu yaklaşım hatayı gizlemek yerine görünür kılar. Exception'ı yakalayıp hiçbir işlem yapmamak, yanıt gövdesini değiştirmez ve asıl nedeni ortadan kaldırmaz; yalnızca programın hata mesajı vermeden devam etmesine yol açar. status_code, başlıklar ve gövde birlikte incelendiğinde hangi katmanda sorun olduğunu daha güvenilir biçimde ayırabilirsiniz.

Belirti, olası neden, kontrol ve çözüm: tek teşhis tablosu

Belirti, olası neden, kontrol ve çözüm: tek teşhis tablosu

response.json() çağrısı başarısız olduğunda önce hatanın JSON ayrıştırma aşamasında oluştuğunu kabul et; fakat nedeni varsayma. Kontrol sırasını response.status_code, Content-Type, response.text, gerekirse response.content ve son olarak gövdenin gerçekten boş olup olmadığı şeklinde ilerlet. Geçerli JSON ayrıştırılması, HTTP isteğinin başarılı olduğunu tek başına kanıtlamaz.

Belirti Olası neden Kontrol Çözüm
Boş veya yalnızca boşluk içeren gövde Yanıt veri içermiyor olabilir. status_code, text.strip(), content Boş gövdeyi ayrıştırma; içerik yok durumunu ayrı yönet.
HTML, düz metin veya sunucu/proxy yanıtı Yanlış yol, giriş sayfası, yönlendirme veya proxy. Content-Type ve text başlangıcı URL, kimlik doğrulama ve yönlendirme ayarlarını düzelt.
Content-Type JSON, fakat JSON bozuk veya yarım Sunucu çıktısı hatalı ya da aktarım kesilmiş olabilir. text ile content içeriğini incele. Yanıt sözleşmesini ve aktarım zincirini araştır; körlemesine yeniden deneme yapma.
Başarılı HTTP durumu, geçersiz gövde 2xx durum kodu veri biçimini garanti etmez. Durum kodundan sonra başlık ve gövdeyi kontrol et. Beklenen biçimi doğrula; gerekiyorsa uygun ayrıştırıcı kullan.
Non-2xx ve geçerli JSON hata gövdesi Sunucu hatayı JSON olarak bildirmiş olabilir. Önce status_code, sonra kontrollü json() HTTP hatasını ayrı işle; hata alanlarını parse başarılıysa oku.
Non-2xx ve JSON olmayan hata gövdesi HTML veya düz metin hata sayfası. Content-Type ve text HTTP hatası olarak raporla; JSON varsayımı yapma.
Hiç response nesnesi oluşmuyor DNS, bağlantı, zaman aşımı, TLS veya proxy sorunu. İstek çağrısındaki exception Ağ istisnasını JSON hatasından ayrı yakala ve ağ ayarlarını incele.
Postman ve Python farklı sonuç veriyor İstek bileşenleri bire bir eşleşmiyor. Metot, URL, parametre, başlık, kimlik ve gövde İstekleri eşleştir; ardından yanıt teşhis sırasına dön.

Postman'da çalışan istek Python'da neden farklı yanıt döndürür?

Postman'daki istek ile Python isteği yalnızca “aynı adrese gidiyor” diye aynı kabul edilmemelidir. Postman; değişkenleri URL, parametre, başlık, kimlik doğrulama ve gövdede kullanabilir; gövde seçimine göre başlıklar ekleyebilir ve çerezleri saklayabilir. Requests ise oturum çerezlerini, yönlendirmeleri ve bazı ortam ayarlarını kendi kurallarına göre yönetir.

  1. HTTP metodunu karşılaştır: GET, POST, PUT veya başka bir metot mu?
  2. Tam URL’yi ve yolu karşılaştır; alan adı, sürüm yolu ve son ek aynı mı?
  3. Sorgu parametrelerini ve değerlerini tek tek eşleştir.
  4. Accept ve Content-Type başlıklarını kontrol et.
  5. Kimlik doğrulama türünü, token’ı ve başlık adını karşılaştır.
  6. Gövde biçimini, JSON kodlamasını, form alanlarını ve karakter kodlamasını incele.
  7. Postman çerezlerinin Python isteğine aktarılıp aktarılmadığını kontrol et.
  8. Yönlendirme davranışını ve oluşan son URL’yi karşılaştır.
  9. Postman ortam değişkenleri ile Python’daki ortam değişkenlerinin değerlerini doğrula.
Hatalı yaklaşım Doğru teşhis akışı
“Postman’da 200 döndü, sorun Python’dadır.” İstek bileşenlerini bire bir eşleştir, sonra yanıtı sırayla incele.
response.json() doğrudan çağrılır. Durum kodu, başlık, text, content ve boşluk kontrolünden sonra dar parse sınırı kullan.
except: pass kullanılır. Teknik bağlamı koru ve kullanıcıya anlaşılır bir hata dön.

Exception’ı bastırmak hatayı çözmez; yalnızca ayrıştırmanın başarısız olduğunu gizler. Aşağıdaki sentetik örnekte gövde HTML olmasına rağmen program “İşlem devam etti” yazabilir:

import json

class SentetikResponse:
    def __init__(self, text):
        self.text = text

    def json(self):
        return json.loads(self.text)

response = SentetikResponse("<html>Giriş sayfası</html>")

try:
    veri = response.json()
except json.JSONDecodeError:
    pass

print("İşlem devam etti")

Doğru yaklaşımda exception, gövdenin başlangıcı ve durum koduyla birlikte teşhis edilir; böylece sorunun ağda mı, HTTP yanıtında mı yoksa JSON biçiminde mi olduğu anlaşılır. API istekleri ve Python hata ayıklama konularındaki bilgi verici teknik yazılar bu teşhis adımlarını farklı örneklerle pekiştirmene yardımcı olabilir.

Çalışabilir mini istemciyle ağ, HTTP ve JSON hatalarını ayırın

Çözüm, doğrudan try-except eklemek değil; hatanın hangi aşamada oluştuğunu ayırmaktır. Önce ağ isteğinin tamamlanıp tamamlanmadığı, ardından status_code, yanıt gövdesi ve son olarak JSON biçimi kontrol edilmelidir. Requests, ağ sorunlarını RequestException ailesiyle; geçersiz JSON gövdesini ise response.json() çağrısı sırasında raporlar.

Hatalı yaklaşım Doğru teşhis akışı
Her şeyi tek bir try-except bloğuna almak ve hatayı bastırmak. Ağ, HTTP durumu, boş gövde ve JSON ayrıştırmayı ayrı aşamalarda incelemek.
except ValueError: pass yazarak devam etmek. Status kodunu, Content-Type değerini ve redakte edilmiş gövde başlangıcını kaydetmek.

Aşağıdaki istemci gerçek bir API adresi kullanmaz. Gerçek isteği yapan bölüm ile sentetik yanıtları inceleyen bölüm birbirinden ayrıdır:

import json
import re
import requests


def safe_preview(text, limit=80):
    text = re.sub(r"(?i)bearers+[^s,]+", "Bearer [REDACTED]", text)
    text = re.sub(
        r'(?i)("(?:access_token|refresh_token|api_key|authorization|token)"s*:s*")[^"]*(")',
        r"1[REDACTED]2",
        text,
    )
    text = " ".join(text.split())
    return text[:limit] + ("..." if len(text) > limit else "")


def detail(label, response):
    content_type = response.headers.get("Content-Type", "<yok>")
    return (
        f"{label}: status_code={response.status_code}, "
        f"Content-Type={content_type}, "
        f"gövde başlangıcı={safe_preview(response.text)}"
    )


def inspect_response(response):
    status = response.status_code
    content_type = response.headers.get("Content-Type", "")

    if status in (401, 403):
        print(detail("Kimlik doğrulama sorunu", response))
        return

    if not 200 <= status < 300:
        print(detail("HTTP durumu başarısız", response))
        return

    if not response.content.strip():
        print(detail("Boş yanıt gövdesi", response))
        return

    if "json" not in content_type.lower():
        print(
            f"Uyarı: Content-Type={content_type or '<yok>'}; "
            "bu başlık JSON olduğunu kanıtlamaz, gövde ayrıca sınanacak."
        )

    try:
        data = response.json()
    except ValueError:
        print(detail("JSON ayrıştırma hatası", response))
        return

    print("JSON başarıyla ayrıştırıldı:", data)


def get_and_inspect(url, headers=None):
    try:
        response = requests.get(
            url,
            headers=headers or {},
            timeout=10,
        )
    except requests.exceptions.RequestException as error:
        print(
            f"Ağ hatası: {type(error).__name__}; "
            "HTTP yanıtı alınamadı."
        )
        return

    inspect_response(response)


class DemoResponse:
    def __init__(self, status_code, content_type, body):
        self.status_code = status_code
        self.headers = {"Content-Type": content_type}
        self.text = body
        self.content = body.encode("utf-8")

    def json(self):
        return json.loads(self.text)


demo_responses = [
    DemoResponse(200, "application/json", '{"ok": true, "items": 2}'),
    DemoResponse(
        200,
        "text/html",
        "<html><body>Giriş sayfası</body></html>",
    ),
]

for demo in demo_responses:
    inspect_response(demo)

Bu iki nesne tamamen sentetiktir; çıktıları gerçek bir API sağlayıcısının yanıtı olarak yorumlanmamalıdır. Beklenen çıktı şöyledir:

JSON başarıyla ayrıştırıldı: {'ok': True, 'items': 2}
Uyarı: Content-Type=text/html; bu başlık JSON olduğunu kanıtlamaz, gövde ayrıca sınanacak.
JSON ayrıştırma hatası: status_code=200, Content-Type=text/html, gövde başlangıcı=<html><body>Giriş sayfası</body></html>

Ön kontrolde json.loads(response.text) kullanmak mümkündür; ancak ardından response.json() çağrılırsa aynı gövde iki kez ayrıştırılmış olur. Çoğu akışta boş gövde ve HTTP kontrollerinden sonra, gerçek ayrıştırmayı yalnızca dar try-except ValueError sınırında bir kez yapmak yeterlidir. Bu tür akışları daha yapılandırılmış biçimde çalışmak isteyenler, birebir Python dersleri kapsamında benzer hata ayıklama örnekleri üzerinde ilerleyebilir.

Sık Sorulan Sorular

status_code 200 olduğu hâlde response.json() neden JSONDecodeError verir?

200 yalnızca HTTP isteğinin başarıyla yanıtlandığını gösterir; gövdenin geçerli JSON olduğunu garanti etmez. Gövde boş olabilir, HTML içerebilir veya bozuk JSON dönebilir.

Content-Type application/json değilse response.json() hiç çağrılmamalı mı?

Hayır. Content-Type önemli bir ipucudur fakat tek başına kanıt değildir. Gövde boş değilse uyarı verip kontrollü biçimde response.json() çağrılabilir; geçersizse dar ValueError bloğu hatayı raporlar.

response.text ile response.content arasındaki fark nedir?

response.text, yanıtı metin olarak ve belirlenen kodlamayı kullanarak sunar. response.content ise yanıt gövdesinin bayt hâlidir; ham kodlamayı incelemek veya ikili içerikle çalışmak gerektiğinde kullanılır.

Postman'da çalışan istek Python'da neden farklı yanıt döndürür?

Python isteğinde HTTP metodu, URL parametreleri, başlıklar, istek gövdesi, kimlik doğrulama bilgileri, çerezler veya yönlendirme davranışı farklı olabilir. Bu nedenle iki isteği yalnızca URL üzerinden değil, bütün istek ayrıntıları üzerinden karşılaştırmak gerekir.

JSONDecodeError aldığımda try-except kullanmak tek başına yeterli midir?

Hayır. try-except programın çökmesini önleyebilir; fakat boş veya HTML gövdenin neden geldiğini açıklamaz. Status kodu, Content-Type ve güvenli gövde ön izlemesi incelenmeden kök neden bulunmuş sayılmaz.

Sağlam bir API istemcisi, JSON ayrıştırmayı son adım olarak ele alır; önce ağın, HTTP yanıtının ve gövdenin gerçekten beklenen yapıda olduğunu doğrular.

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