What Exceptions Can Be Raised by Python Httpx's Json() Method?
The Excellent Python Httpx Package Has A. Json() Method for Conveniently Decoding Resposnes That Are in Json Format. but the Documentation Does Not Mention...
The excellent Python HTTPX package has a .json() method for conveniently decoding resposnes that are in JSON format. But the documentation does not mention what exceptions can be raised by .json(), and even looking through the code, it is not obvious to me what the possible exceptions might be.
For purposes of writing code like the following,
try:
return response.json()
except EXCEPTION:
print('This is not the JSON you are looking for')
what exceptions should I test for?
1 Answer
even looking through the code, it is not obvious to me what the possible exceptions might be.
Here's my attempt at looking through it:
def json(self, **kwargs: typing.Any) -> typing.Any:
if self.charset_encoding is None and self.content and len(self.content) > 3:
encoding = guess_json_utf(self.content)
if encoding is not None:
return jsonlib.loads(self.content.decode(encoding), **kwargs)
return jsonlib.loads(self.text, **kwargs)
self.contentcan raiseResponseNotReadif (as it sounds like) the response has not been read yet. However, this is almost certainly due to a logical error in the code rather than any meaningful problem at runtime worth detecting; so there is no good reason to catch this. (It also wouldn't happen with the most straightforward use cases, such as the one shown in the documentation.) Otherwise,self.contentwill be abytes, solenwill work.self.charset_encodingwill either returnNone(if there is no corresponding data in the response header) or else eventually use the standard libraryemail.message.Message.get_content_charsetto parse a content type from the response header. The latter is not documented to raise any exceptions; so there should not be any exception from accessing this value.guess_json_utfwill necessarily be passed abytesthat is at least 4 bytes long. Nothing in its logic should be able to fail under those conditions. EitherNoneor a string will be returned.If
jsonlib.loadsis called usingself.content.decode(encoding), thenencodingwas necessarily notNone, and is a valid encoding name returned fromguess_json_utfHowever, it's possible that theself.content(bytesdata) is not valid data (i.e., convertible to text using the guessed text encoding). This would causeUnicodeDecodeError.Otherwise, it's called with
self.text. If the underlying_textwas set before, it will be a string and gets returned. If there is no content in the response, an empty string is returned. Otherwise, decoding is attempted using a default text encoder with a"replace"error-handling policy. There again shouldn't be anything that could cause the text encoding name to be invalid, so again this can only raiseUnicodeDecodeError, and even that shouldn't be possible with the"replace"error-handling policy.Finally:
jsonlib.loadsis simplyjson.loads(i.e., the standard libraryjson). if the code gets this far,json.loadswill definitely be given a string to load; all possible issues with the string contents will be reported asJSONDecodeError.
tl;dr: the possible exceptions that make sense to catch are JSONDecodeError (the response is not valid JSON - this includes e.g. an empty response) and UnicodeDecodeError (the response is corrupt in some way, for example it mixes bytes intended to encode text in two different ways, or it's supposed to be UTF-8 but contains bytes that are illegal in that encoding; or it's encoded using a non-UTF scheme, such as Latin-1, in a way that is incompatible with the corresponding guessed UTF scheme, and doesn't advertise the encoding in the header).