Skip to content

Commit 6f4ae37

Browse files
Backport PR pandas-dev#31748: BUG: Fixed encoding of pd.NA with to_json (pandas-dev#31804)
Co-authored-by: Kendall Masse <[email protected]>
1 parent 6ed4cd2 commit 6f4ae37

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

doc/source/whatsnew/v1.0.2.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ Fixed regressions
2525
Bug fixes
2626
~~~~~~~~~
2727

28-
-
29-
-
28+
**I/O**
29+
30+
- Using ``pd.NA`` with :meth:`DataFrame.to_json` now correctly outputs a null value instead of an empty object (:issue:`31615`)
3031

3132
.. ---------------------------------------------------------------------------
3233

pandas/_libs/src/ujson/python/objToJSON.c

+12
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ static PyTypeObject *cls_dataframe;
5454
static PyTypeObject *cls_series;
5555
static PyTypeObject *cls_index;
5656
static PyTypeObject *cls_nat;
57+
static PyTypeObject *cls_na;
5758
PyObject *cls_timedelta;
5859

5960
npy_int64 get_nat(void) { return NPY_MIN_INT64; }
@@ -151,6 +152,7 @@ int PdBlock_iterNext(JSOBJ, JSONTypeContext *);
151152
void *initObjToJSON(void) {
152153
PyObject *mod_pandas;
153154
PyObject *mod_nattype;
155+
PyObject *mod_natype;
154156
PyObject *mod_decimal = PyImport_ImportModule("decimal");
155157
type_decimal =
156158
(PyTypeObject *)PyObject_GetAttrString(mod_decimal, "Decimal");
@@ -176,6 +178,12 @@ void *initObjToJSON(void) {
176178
Py_DECREF(mod_nattype);
177179
}
178180

181+
mod_natype = PyImport_ImportModule("pandas._libs.missing");
182+
if (mod_natype) {
183+
cls_na = (PyTypeObject *)PyObject_GetAttrString(mod_natype, "NAType");
184+
Py_DECREF(mod_natype);
185+
}
186+
179187
/* Initialise numpy API */
180188
import_array();
181189
// GH 31463
@@ -1909,6 +1917,10 @@ void Object_beginTypeContext(JSOBJ _obj, JSONTypeContext *tc) {
19091917
"%R (0d array) is not JSON serializable at the moment",
19101918
obj);
19111919
goto INVALID;
1920+
} else if (PyObject_TypeCheck(obj, cls_na)) {
1921+
PRINTMARK();
1922+
tc->type = JT_NULL;
1923+
return;
19121924
}
19131925

19141926
ISITERABLE:

pandas/tests/io/json/test_pandas.py

+10
Original file line numberDiff line numberDiff line change
@@ -1640,3 +1640,13 @@ def test_deprecate_numpy_argument_read_json(self):
16401640
with tm.assert_produces_warning(FutureWarning):
16411641
result = read_json(expected.to_json(), numpy=True)
16421642
tm.assert_frame_equal(result, expected)
1643+
1644+
def test_json_pandas_na(self):
1645+
# GH 31615
1646+
result = pd.DataFrame([[pd.NA]]).to_json()
1647+
assert result == '{"0":{"0":null}}'
1648+
1649+
def test_json_pandas_nulls(self, nulls_fixture):
1650+
# GH 31615
1651+
result = pd.DataFrame([[nulls_fixture]]).to_json()
1652+
assert result == '{"0":{"0":null}}'

0 commit comments

Comments
 (0)