Skip to content

Commit

Permalink
Update ujson handling of unsupported types (#37)
Browse files Browse the repository at this point in the history
Include upstream modifications:

* Removed generic serialization of objects/iterables: ultrajson/ultrajson@53f85b1
* Fix "�� is not JSON serializable" on Python 3: ultrajson/ultrajson#382
  • Loading branch information
adrianeboyd committed Nov 10, 2020
1 parent 74ac111 commit 8112974
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 209 deletions.
8 changes: 8 additions & 0 deletions srsly/tests/test_json_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
from io import StringIO
from pathlib import Path
import gzip
import numpy

from .._json_api import read_json, write_json, read_jsonl, write_jsonl
from .._json_api import write_gzip_json, json_dumps, is_json_serializable
from .._json_api import json_dumps
from ..util import force_string
from .util import make_tempdir

Expand Down Expand Up @@ -174,3 +176,9 @@ def test_write_jsonl_stdout(capsys):
)
def test_is_json_serializable(obj, expected):
assert is_json_serializable(obj) == expected


def test_unsupported_type_error():
f = numpy.float32()
with pytest.raises(TypeError):
s = json_dumps(f)
219 changes: 10 additions & 209 deletions srsly/ujson/objToJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,164 +256,6 @@ char *Tuple_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
return NULL;
}

int Iter_iterNext(JSOBJ obj, JSONTypeContext *tc)
{
PyObject *item;

if (GET_TC(tc)->itemValue)
{
Py_DECREF(GET_TC(tc)->itemValue);
GET_TC(tc)->itemValue = NULL;
}

if (GET_TC(tc)->iterator == NULL)
{
return 0;
}

item = PyIter_Next(GET_TC(tc)->iterator);

if (item == NULL)
{
return 0;
}

GET_TC(tc)->itemValue = item;
return 1;
}

void Iter_iterEnd(JSOBJ obj, JSONTypeContext *tc)
{
if (GET_TC(tc)->itemValue)
{
Py_DECREF(GET_TC(tc)->itemValue);
GET_TC(tc)->itemValue = NULL;
}

if (GET_TC(tc)->iterator)
{
Py_DECREF(GET_TC(tc)->iterator);
GET_TC(tc)->iterator = NULL;
}
}

JSOBJ Iter_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
{
return GET_TC(tc)->itemValue;
}

char *Iter_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
{
return NULL;
}

void Dir_iterEnd(JSOBJ obj, JSONTypeContext *tc)
{
if (GET_TC(tc)->itemValue)
{
Py_DECREF(GET_TC(tc)->itemValue);
GET_TC(tc)->itemValue = NULL;
}

if (GET_TC(tc)->itemName)
{
Py_DECREF(GET_TC(tc)->itemName);
GET_TC(tc)->itemName = NULL;
}

Py_DECREF( (PyObject *) GET_TC(tc)->attrList);
PRINTMARK();
}

int Dir_iterNext(JSOBJ _obj, JSONTypeContext *tc)
{
PyObject *obj = (PyObject *) _obj;
PyObject *itemValue = GET_TC(tc)->itemValue;
PyObject *itemName = GET_TC(tc)->itemName;
PyObject* attr;
PyObject* attrName;
char* attrStr;

if (itemValue)
{
Py_DECREF(GET_TC(tc)->itemValue);
GET_TC(tc)->itemValue = itemValue = NULL;
}

if (itemName)
{
Py_DECREF(GET_TC(tc)->itemName);
GET_TC(tc)->itemName = itemName = NULL;
}

for (; GET_TC(tc)->index < GET_TC(tc)->size; GET_TC(tc)->index ++)
{
attrName = PyList_GET_ITEM(GET_TC(tc)->attrList, GET_TC(tc)->index);
#if PY_MAJOR_VERSION >= 3
attr = PyUnicode_AsUTF8String(attrName);
#else
attr = attrName;
Py_INCREF(attr);
#endif
attrStr = PyString_AS_STRING(attr);

if (attrStr[0] == '_')
{
PRINTMARK();
Py_DECREF(attr);
continue;
}

itemValue = PyObject_GetAttr(obj, attrName);
if (itemValue == NULL)
{
PyErr_Clear();
Py_DECREF(attr);
PRINTMARK();
continue;
}

if (PyCallable_Check(itemValue))
{
Py_DECREF(itemValue);
Py_DECREF(attr);
PRINTMARK();
continue;
}

PRINTMARK();
itemName = attr;
break;
}

if (itemName == NULL)
{
GET_TC(tc)->index = GET_TC(tc)->size;
GET_TC(tc)->itemValue = NULL;
return 0;
}

GET_TC(tc)->itemName = itemName;
GET_TC(tc)->itemValue = itemValue;
GET_TC(tc)->index ++;

PRINTMARK();
return 1;
}

JSOBJ Dir_iterGetValue(JSOBJ obj, JSONTypeContext *tc)
{
PRINTMARK();
return GET_TC(tc)->itemValue;
}

char *Dir_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
{
PRINTMARK();
*outLen = PyString_GET_SIZE(GET_TC(tc)->itemName);
return PyString_AS_STRING(GET_TC(tc)->itemName);
}

int List_iterNext(JSOBJ obj, JSONTypeContext *tc)
{
if (GET_TC(tc)->index >= GET_TC(tc)->size)
Expand Down Expand Up @@ -658,7 +500,7 @@ void SetupDictIter(PyObject *dictObj, TypeContext *pc, JSONObjectEncoder *enc)

void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObjectEncoder *enc)
{
PyObject *obj, *exc, *iter;
PyObject *obj, *objRepr, *exc;
TypeContext *pc;
PRINTMARK();
if (!_obj)
Expand Down Expand Up @@ -822,20 +664,6 @@ void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObjectEncoder

return;
}
/*
else
if (PyAnySet_Check(obj))
{
PRINTMARK();
tc->type = JT_ARRAY;
pc->iterBegin = NULL;
pc->iterEnd = Iter_iterEnd;
pc->iterNext = Iter_iterNext;
pc->iterGetValue = Iter_iterGetValue;
pc->iterGetName = Iter_iterGetName;
return;
}
*/

if (PyObject_HasAttrString(obj, "toDict"))
{
Expand Down Expand Up @@ -899,42 +727,15 @@ void Object_beginTypeContext (JSOBJ _obj, JSONTypeContext *tc, JSONObjectEncoder
PRINTMARK();
PyErr_Clear();

iter = PyObject_GetIter(obj);

if (iter != NULL)
{
PRINTMARK();
tc->type = JT_ARRAY;
pc->iterator = iter;
pc->iterEnd = Iter_iterEnd;
pc->iterNext = Iter_iterNext;
pc->iterGetValue = Iter_iterGetValue;
pc->iterGetName = Iter_iterGetName;
return;
}

PRINTMARK();
PyErr_Clear();

PRINTMARK();
tc->type = JT_OBJECT;
GET_TC(tc)->attrList = PyObject_Dir(obj);

if (GET_TC(tc)->attrList == NULL)
{
PyErr_Clear();
goto INVALID;
}

GET_TC(tc)->index = 0;
GET_TC(tc)->size = PyList_GET_SIZE(GET_TC(tc)->attrList);
PRINTMARK();

pc->iterEnd = Dir_iterEnd;
pc->iterNext = Dir_iterNext;
pc->iterGetValue = Dir_iterGetValue;
pc->iterGetName = Dir_iterGetName;
return;
objRepr = PyObject_Repr(obj);
#if PY_MAJOR_VERSION >= 3
PyObject* str = PyUnicode_AsEncodedString(objRepr, "utf-8", "~E~");
PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(str));
Py_XDECREF(str);
#else
PyErr_Format (PyExc_TypeError, "%s is not JSON serializable", PyString_AS_STRING(objRepr));
#endif
Py_DECREF(objRepr);

INVALID:
PRINTMARK();
Expand Down

0 comments on commit 8112974

Please sign in to comment.