Mar-30-2019, 09:28 PM
Python's JSON module supports deserializing Javascript infinities (although the official JSON spec doesn't). Specifically, it supports "Infinity" and "-Infinity" in particular. I need to be able to deserialize "+Infinity" though. Here is my attempt at achieving this
What does work is catching a StopIteration exception, but that doesn't seem right. I'm afraid that there's something weird going on here and if I catch the wrong exception, there will be some surprise down the line. Does anyone know what's going on here?
import json
class PositiveInfinityJSONDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.original_scan_once = self.scan_once
self.scan_once = self._scan_once
def _scan_once(self, string, idx):
print("Custom _scan_once entered; trying default first...")
try:
return self.original_scan_once(string, idx)
except json.decoder.JSONDecodeError as e:
print("Default failed, trying custom logic...")
try:
nextchar = string[idx]
except IndexError:
raise StopIteration(idx) from e
if nextchar == '+' and string[idx:idx + 9] == '+Infinity':
return self.parse_constant('Infinity'), idx + 9
raise e
except Exception as e:
print(f"Got an unexpected exception from default (type: {type(e)}) - {e}")
raise e
print(json.loads('+Infinity', cls=PositiveInfinityJSONDecoder))The result of this is that (apparently) a StopIteration exception is thrown, although its traceback looks like a JSONDecodeErrorOutput:$ python3 confusion.py
Custom _scan_once entered; trying default first...
Got an unexpected exception from default (type: <class 'StopIteration'>) - 0
Traceback (most recent call last):
File "confusion.py", line 28, in <module>
print(json.loads('+Infinity', cls=PositiveInfinityJSONDecoder))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 361, in loads
return cls(**kw).decode(s)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)I'm baffled because the stack trace clearly shows a JSONDecodeError being raised, but at runtime when I try to catch it, it appears to have a different type. In case the class is doing something funky, I also tried catching a ValueError (its superclass) but that didn't work either.What does work is catching a StopIteration exception, but that doesn't seem right. I'm afraid that there's something weird going on here and if I catch the wrong exception, there will be some surprise down the line. Does anyone know what's going on here?
