Skip to content

Commit 03ccc34

Browse files
committed
Merge pull request #10306 from behzadnouri/json-mixed-type
BUG: bug in json serialization when frame has mixed types
2 parents c5d15a0 + 9d30b91 commit 03ccc34

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

doc/source/whatsnew/v0.16.2.txt

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ Bug Fixes
124124

125125
- Bug in groupby.apply aggregation for Categorical not preserving categories (:issue:`10138`)
126126
- Bug in ``to_csv`` where ``date_format`` is ignored if the ``datetime`` is fractional (:issue:`10209`)
127+
- Bug in ``DataFrame.to_json`` with mixed data types (:issue:`10289`)
127128

128129
- Bug in cache updating when consolidating (:issue:`10264`)
129130

pandas/io/tests/test_json/test_pandas.py

+27
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,33 @@ def test_frame_empty_mixedtype(self):
333333
self.assertTrue(df._is_mixed_type)
334334
assert_frame_equal(read_json(df.to_json(), dtype=dict(df.dtypes)), df)
335335

336+
def test_frame_mixedtype_orient(self): # GH10289
337+
vals = [[10, 1, 'foo', .1, .01],
338+
[20, 2, 'bar', .2, .02],
339+
[30, 3, 'baz', .3, .03],
340+
[40, 4, 'qux', .4, .04]]
341+
342+
df = DataFrame(vals, index=list('abcd'),
343+
columns=['1st', '2nd', '3rd', '4th', '5th'])
344+
345+
self.assertTrue(df._is_mixed_type)
346+
right = df.copy()
347+
348+
for orient in ['split', 'index', 'columns']:
349+
inp = df.to_json(orient=orient)
350+
left = read_json(inp, orient=orient, convert_axes=False)
351+
assert_frame_equal(left, right)
352+
353+
right.index = np.arange(len(df))
354+
inp = df.to_json(orient='records')
355+
left = read_json(inp, orient='records', convert_axes=False)
356+
assert_frame_equal(left, right)
357+
358+
right.columns = np.arange(df.shape[1])
359+
inp = df.to_json(orient='values')
360+
left = read_json(inp, orient='values', convert_axes=False)
361+
assert_frame_equal(left, right)
362+
336363
def test_v12_compat(self):
337364
df = DataFrame(
338365
[[1.56808523, 0.65727391, 1.81021139, -0.17251653],

pandas/src/ujson/lib/ultrajson.h

+1
Original file line numberDiff line numberDiff line change
@@ -309,5 +309,6 @@ typedef struct __JSONObjectDecoder
309309
} JSONObjectDecoder;
310310

311311
EXPORTFUNCTION JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuffer);
312+
EXPORTFUNCTION void encode(JSOBJ, JSONObjectEncoder *, const char *, size_t);
312313

313314
#endif

pandas/src/ujson/lib/ultrajsondec.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ FASTCALL_ATTR JSOBJ FASTCALL_MSVC decode_object( struct DecoderState *ds)
803803
return NULL;
804804
}
805805

806-
if (!ds->dec->objectAddKey (ds->prv, newObj, itemName, itemValue))
806+
if (!ds->dec->objectAddKey (ds->prv, newObj, itemName, itemValue))
807807
{
808808
ds->dec->releaseObject(ds->prv, newObj, ds->dec);
809809
ds->dec->releaseObject(ds->prv, itemName, ds->dec);
@@ -907,7 +907,7 @@ JSOBJ JSON_DecodeObject(JSONObjectDecoder *dec, const char *buffer, size_t cbBuf
907907
setlocale(LC_NUMERIC, locale);
908908
free(locale);
909909
}
910-
else
910+
else
911911
{
912912
ret = decode_any (&ds);
913913
}

pandas/src/ujson/python/objToJSON.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ enum PANDAS_FORMAT
161161
//#define PRINTMARK() fprintf(stderr, "%s: MARK(%d)\n", __FILE__, __LINE__)
162162
#define PRINTMARK()
163163

164+
int PdBlock_iterNext(JSOBJ, JSONTypeContext *);
165+
164166
// import_array() compat
165167
#if (PY_VERSION_HEX >= 0x03000000)
166168
void *initObjToJSON(void)
@@ -835,7 +837,10 @@ char *PdBlock_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
835837
}
836838
else
837839
{
838-
idx = npyarr->index[npyarr->stridedim - npyarr->inc] - 1;
840+
idx = GET_TC(tc)->iterNext != PdBlock_iterNext
841+
? npyarr->index[npyarr->stridedim - npyarr->inc] - 1
842+
: npyarr->index[npyarr->stridedim];
843+
839844
NpyArr_getLabel(obj, tc, outLen, idx, npyarr->rowLabels);
840845
}
841846
return NULL;
@@ -2374,7 +2379,7 @@ void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc)
23742379
}
23752380
goto INVALID;
23762381
}
2377-
encode (tmpObj, enc, NULL, 0);
2382+
encode (tmpObj, (JSONObjectEncoder*) enc, NULL, 0);
23782383
Py_DECREF(tmpObj);
23792384
goto INVALID;
23802385
}

0 commit comments

Comments
 (0)