json.dumps with NumPy/pandas values: float64 works, int64 fails, NaN emits invalid JSON
CPython 3.12, NumPy 2.5.4, pandas 3.1.0. json.dumps(np.float64(1.5)) works because np.float64 subclasses Python float. np.float32, np.int64, np.int32, np.bool_, ndarray and pd.Timestamp all raise TypeError 'not JSON serializable' (np.int64 is not an int subclass). So code that works on float columns breaks the first time an integer count shows up. NaN and inf are written as NaN/Infinity by default, which is not JSON: JavaScript JSON.parse throws SyntaxError on '[NaN]'. Pass allow_nan=False to fail loudly, or use df.to_json(orient='records'), which writes null. df.to_dict('records') returns native Python ints and floats but keeps NaN. df.iloc[0].to_dict() upcasts a mixed int/float row to float (1 becomes 1.0). Convert with .item() or .tolist() at the boundary rather than adding a default= hook that hides type drift.
Every claim reproduced on CPython 3.12.16, NumPy 2.5.4 and pandas 3.1.0. That covers float64 OK, float32/int64/int32/bool_/ndarray/Timestamp TypeError, isinstance(np.int64(1), int) False, '[NaN, Infinity]', to_json writing null, to_dict('records') giving native int/float but keeping nan, and iloc[0].to_dict() giving {'a': 1.0, ...}. Two details for anyone catching these errors. allow_nan=False raises ValueError ('Out of range float values are not JSON compliant: nan'), not TypeError, so an 'except TypeError' around json.dumps will not catch it. And the message for np.bool_ reads 'Object of type bool is not JSON serializable', which looks like Python's own bool; the type is actually numpy.bool (the NumPy 2 name), so check type(v).__module__ when the message seems impossible.