From 99d47a1943918b73eedcda9f84050201eeaebfc3 Mon Sep 17 00:00:00 2001 From: behzad nouri Date: Fri, 3 Apr 2015 07:53:26 -0400 Subject: [PATCH] bug in json lib when frame has length zero --- doc/source/whatsnew/v0.16.1.txt | 1 + pandas/io/tests/test_json/test_pandas.py | 10 +++++++++ pandas/src/ujson/python/objToJSON.c | 27 +++++++++++++----------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/doc/source/whatsnew/v0.16.1.txt b/doc/source/whatsnew/v0.16.1.txt index 8c49e2780ed06..f6032a65c32f1 100644 --- a/doc/source/whatsnew/v0.16.1.txt +++ b/doc/source/whatsnew/v0.16.1.txt @@ -61,6 +61,7 @@ Bug Fixes ~~~~~~~~~ - Fixed bug (:issue:`9542`) where labels did not appear properly in legend of ``DataFrame.plot()``. Passing ``label=`` args also now works, and series indices are no longer mutated. +- Bug in json serialization when frame has length zero.(:issue:`9805`) - Bug in ``scatter_matrix`` draws unexpected axis ticklabels (:issue:`5662`) diff --git a/pandas/io/tests/test_json/test_pandas.py b/pandas/io/tests/test_json/test_pandas.py index 7fe9cd9ce5cdf..1e8ce7afa9492 100644 --- a/pandas/io/tests/test_json/test_pandas.py +++ b/pandas/io/tests/test_json/test_pandas.py @@ -321,6 +321,16 @@ def test_frame_to_json_except(self): df = DataFrame([1, 2, 3]) self.assertRaises(ValueError, df.to_json, orient="garbage") + def test_frame_empty(self): + df = DataFrame(columns=['jim', 'joe']) + self.assertFalse(df._is_mixed_type) + assert_frame_equal(read_json(df.to_json()), df) + + # mixed type + df['joe'] = df['joe'].astype('i8') + self.assertTrue(df._is_mixed_type) + assert_frame_equal(read_json(df.to_json()), df) + def test_v12_compat(self): df = DataFrame( [[1.56808523, 0.65727391, 1.81021139, -0.17251653], diff --git a/pandas/src/ujson/python/objToJSON.c b/pandas/src/ujson/python/objToJSON.c index 75967bce87f76..38ce67e0fc28e 100644 --- a/pandas/src/ujson/python/objToJSON.c +++ b/pandas/src/ujson/python/objToJSON.c @@ -457,7 +457,7 @@ static void *PyTimeToJSON(JSOBJ _obj, JSONTypeContext *tc, void *outValue, size_ PyErr_SetString(PyExc_ValueError, "Failed to convert time"); return NULL; } - if (PyUnicode_Check(str)) + if (PyUnicode_Check(str)) { tmp = str; str = PyUnicode_AsUTF8String(str); @@ -479,7 +479,7 @@ static int NpyTypeToJSONType(PyObject* obj, JSONTypeContext* tc, int npyType, vo { PRINTMARK(); castfunc = PyArray_GetCastFunc(PyArray_DescrFromType(npyType), NPY_DOUBLE); - if (!castfunc) + if (!castfunc) { PyErr_Format ( PyExc_ValueError, @@ -501,7 +501,7 @@ static int NpyTypeToJSONType(PyObject* obj, JSONTypeContext* tc, int npyType, vo { PRINTMARK(); castfunc = PyArray_GetCastFunc(PyArray_DescrFromType(npyType), NPY_INT64); - if (!castfunc) + if (!castfunc) { PyErr_Format ( PyExc_ValueError, @@ -584,7 +584,12 @@ void NpyArr_iterBegin(JSOBJ _obj, JSONTypeContext *tc) obj = (PyArrayObject *) _obj; } - if (PyArray_SIZE(obj) > 0) + if (PyArray_SIZE(obj) < 0) + { + PRINTMARK(); + GET_TC(tc)->iterNext = NpyArr_iterNextNone; + } + else { PRINTMARK(); npyarr = PyObject_Malloc(sizeof(NpyArrContext)); @@ -624,11 +629,6 @@ void NpyArr_iterBegin(JSOBJ _obj, JSONTypeContext *tc) npyarr->columnLabels = GET_TC(tc)->columnLabels; npyarr->rowLabels = GET_TC(tc)->rowLabels; } - else - { - PRINTMARK(); - GET_TC(tc)->iterNext = NpyArr_iterNextNone; - } } void NpyArr_iterEnd(JSOBJ obj, JSONTypeContext *tc) @@ -1054,8 +1054,11 @@ void PdBlock_iterBegin(JSOBJ _obj, JSONTypeContext *tc) npyarr = GET_TC(tc)->npyarr; // set the dataptr to our desired column and initialise - npyarr->dataptr += npyarr->stride * idx; - NpyArr_iterNext(obj, tc); + if (npyarr != NULL) + { + npyarr->dataptr += npyarr->stride * idx; + NpyArr_iterNext(obj, tc); + } GET_TC(tc)->itemValue = NULL; ((PyObjectEncoder*) tc->encoder)->npyCtxtPassthru = NULL; @@ -2624,7 +2627,7 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs) if (odefHandler != NULL && odefHandler != Py_None) { - if (!PyCallable_Check(odefHandler)) + if (!PyCallable_Check(odefHandler)) { PyErr_SetString (PyExc_TypeError, "Default handler is not callable"); return NULL;