The error means your code calls .json on a None value; fix it by validating the object and handling non-JSON cases.
Hitting attributeerror: ‘nonetype’ object has no attribute ‘json’ can stall a task that should be trivial: read JSON and move on. The message is plain: a variable you expect to be a response or payload isn’t an object with a .json() method; it’s None. In Python, that triggers an AttributeError when you try to access a method or attribute that doesn’t exist on that value.
What This Error Means In Plain Python
Quick check: find the symbol just left of .json in your code and print its type. If it’s <class 'NoneType'>, you’re calling a method on a missing object. In Python, AttributeError is raised when an attribute reference fails, and that includes trying to call a method that doesn’t exist on a type. Names are case-sensitive too: .Json isn’t the same as .json().
- Confirm the object: add
print(type(obj), obj)or a debugger breakpoint right beforeobj.json(). - Guard the call: use a short conditional like
if obj is None: ...before method access. - Fix the name: use the exact method name for your library; requests uses
Response.json()with lowercase.
Common Triggers In Real Projects
Several recurring patterns lead to attributeerror: ‘nonetype’ object has no attribute ‘json’. Track them down with tight, single-purpose checks.
- Requests response variable is
None: a function wrapped your HTTP call and returned nothing on error, so the caller receivedNoneand still tried.json(). Requests’ top-level methods (get,post, etc.) themselves return aResponseobject, so a barerequests.get(...)doesn’t yieldNone; your wrapper likely does. - Flask request body isn’t JSON:
request.get_json()returnsNonewhen the request isn’t tagged as JSON (wrongContent-Typeheader) or the body can’t be parsed. - Method/property mismatch or casing: using
.Jsonor.jsonwithout calling it as a function; or accessing.jsonon adictreturned from a prior call tor.json(). - Chained
dict.get()returnsNone:payload.get("data")may beNone, then.json()on it fails. - Async/flow bugs: a code path returns early with no value; the caller still assumes a
Response.
AttributeError: ‘NoneType’ Object Has No Attribute ‘Json’ — Fixes By Scenario
Pick the case that matches your stack. Each block gives a tight diagnosis, a minimal fix, and a quick test to prove it’s resolved.
Requests: Calling .json() On A Missing Or Failed Response
Diagnosis: your helper returns None on network errors or non-200 status; the caller still runs .json(). Requests returns a Response object; success isn’t implied by r.json() itself. Check the status first.
import requests
def fetch_json(url, **kw):
r = requests.get(url, timeout=10, **kw) # Response object
r.raise_for_status() # raises for 4xx/5xx
return r.json() # parse body as JSON
try:
data = fetch_json("https://httpbin.org/json")
except requests.HTTPError as e:
# handle HTTP errors cleanly
print("http error:", e)
except requests.RequestException as e:
print("network error:", e)
else:
print("ok:", type(data))
- Raise for status: call
r.raise_for_status()before parsing; it surfaces server failures early. - Return the response or data consistently: never return
Noneon error without also changing the function’s type contract. - Add a timeout: prevent hung calls that tempt “return
None” patches later.
Flask: request.get_json() Returns None
Diagnosis: the client didn’t send Content-Type: application/json, the body is empty, or parsing failed. By default, Flask returns None in these cases.
# server.py
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.post("/ingest")
def ingest():
payload = request.get_json(silent=True) # None if not JSON
if payload is None:
return jsonify(error="send JSON with Content-Type application/json"), 400
# process safely
return jsonify(ok=True, size=len(payload))
# client: set Content-Type and send a JSON body
curl -X POST http://localhost:5000/ingest \
-H "Content-Type: application/json" \
-d '{"name":"Rikta","count":3}'
- Set the header: send the correct
Content-Typeand valid JSON; thenget_json()yields a Python object. - Use
silent=Truewith care: it returnsNonewhen parsing fails; handle that path explicitly.
Wrong Attribute Name Or Missing Call
Diagnosis: a small typo: .Json or .json without parentheses. Method names are case-sensitive; forgetting the call turns a function object into a truthy value, not parsed data. Python raises AttributeError or later logic breaks.
# wrong
data = response.Json # case mismatch
data = response.json # forgot parentheses
# right
data = response.json()
Chained dict.get(...) Returned None
Diagnosis: code like payload.get("data").json() fails when the key is missing. get() returns None by default.
# safer chain
node = payload.get("data")
if not isinstance(node, dict):
raise ValueError("missing 'data' object")
# proceed with node[...] access or convert with json.dumps if needed
- Provide a default:
payload.get("data", {})gives a dict instead ofNone; still validate its shape. - Add type checks: keep guards near the access point.
Helper Function Returned Nothing
Diagnosis: a function exits without a return statement on some path. The caller expects a response-like object and does .json().
def maybe_fetch(flag):
if flag:
return requests.get("https://httpbin.org/json")
# no return here ⇒ returns None
resp = maybe_fetch(False)
if resp is None:
# handle the branch; do not call .json()
resp = {"fallback": True}
Quick Checks Before You Dive Into Logs
These fast steps often surface the root cause in minutes.
- Print the type:
print(type(obj))right before the call; the traceback tells you which line to instrument. - Confirm the library contract: verify what a function returns on success and failure in the docs; requests methods return
Responseobjects. - Check status then parse: for HTTP, call
raise_for_status()and only then.json(). - Validate headers on APIs: send
Content-Type: application/jsonfor JSON POSTs to Flask.
Reliable Patterns That Prevent The Error
Adopt small patterns that make AttributeError less likely and easier to find.
- Return one type per function: either always return a
Response/dict, or raise; don’t returnNoneon failure and data on success. - Add guards at boundaries: when reading network or user input, check types and required keys early.
- Prefer explicit parsing: unwrap JSON only where you need it; keep raw
Responsearound when headers and status matter. - Centralize error handling: one HTTP helper with retries, timeouts, and status checks reduces drift. Requests documents status handling with
raise_for_status(). - Use type hints and linters: hint return types (
-> dictor-> Response) and run a static checker; it flagsOptionalmisuse quickly.
Symptom-To-Fix Table
| Symptom | Likely Cause | Fix |
|---|---|---|
Traceback shows obj.json() on line N |
obj is None |
Print type(obj); add a guard or return a real object |
HTTP call seems fine, then .json() fails |
Wrapper returned None on error |
Raise on non-200, return consistent types; only parse on success |
Flask endpoint sees None from get_json() |
Wrong header or invalid body | Send Content-Type: application/json; validate body; use silent=True with checks |
Code uses .Json or misses () |
Case mismatch or not calling the function | Use .json() exactly; Python attributes are case-sensitive |
Worked Examples You Can Paste Into Your Project
Requests: Safe Parse With Status Check
import requests
def safe_get_json(url, **kw):
r = requests.get(url, timeout=10, **kw)
r.raise_for_status() # raise first
try:
return r.json() # parse body
except ValueError as e:
# body isn't JSON
raise RuntimeError(f"non-JSON response from {url}") from e
# usage
data = safe_get_json("https://httpbin.org/json")
This pattern enforces “raise then parse,” which the requests docs recommend when you need to check success before decoding JSON.
Flask: Client And Server In Sync
# client.js (fetch)
fetch("/ingest", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ project: "alpha", ok: true })
})
# server route
from flask import request, jsonify
@app.post("/ingest")
def ingest():
data = request.get_json(silent=True) # None if bad/missing JSON
if data is None:
return jsonify(error="send JSON with Content-Type application/json"), 400
return jsonify(received=bool(data))
Flask’s get_json returns None when the mimetype isn’t JSON unless you force parsing; handle that path explicitly.
Defensive Wrapper That Never Returns None
from typing import Any, Dict
import requests
class HttpError(RuntimeError):
pass
def get_json_or_error(url: str) -> Dict[str, Any]:
r = requests.get(url, timeout=10)
if 200 <= r.status_code < 300:
try:
return r.json()
except ValueError as e:
raise HttpError("response body is not JSON") from e
raise HttpError(f"bad status {r.status_code}")
Why The Message Mentions 'Json'
If your code literally uses .Json with a capital J, Python looks for an attribute named Json and won’t find it on a Response, even when the object isn’t None. On a None value, any attribute (including Json) fails. Requests documents the correct method name as json() on Response.
Recap: Minimal Rules To Avoid The Error Next Time
- Check success, then parse: call
raise_for_status()first; only then call.json(). - Match client and server: send the right headers; validate at the route; expect
Nonefromget_json()on bad input. - Return consistent types: do not return
Noneon error where aResponseis expected. - Spell the method exactly:
.json(), not.Json; call it with parentheses.
