Python-cjson为python实现了一个非常快速的json编码器/解码器。同其他用python实现的json编码器/解码器比较,在编码方面,速度快10-200倍;在解码方面,速度快100-250倍。
github地址如下:github.com/AGProjects/…
源码只包含一个文件,cjson.c。提供的两个接口是:encode和decode。其中encode把Python对象转成json对象,decode是把json对象,转成Python的对象。
encode
依次检查Python的对象类型,然后转成string。
static PyObject*
encode_object(PyObject *object)
{
if (object == Py_True) {
return PyString_FromString("true");
} else if (object == Py_False) {
return PyString_FromString("false");
} else if (object == Py_None) {
return PyString_FromString("null");
} else if (PyString_Check(object)) {
return encode_string(object);
} else if (PyUnicode_Check(object)) {
return encode_unicode(object);
} else if (PyFloat_Check(object)) {
double val = PyFloat_AS_DOUBLE(object);
if (Py_IS_NAN(val)) {
return PyString_FromString("NaN");
} else if (Py_IS_INFINITY(val)) {
if (val > 0) {
return PyString_FromString("Infinity");
} else {
return PyString_FromString("-Infinity");
}
} else {
return PyObject_Repr(object);
}
} else if (PyInt_Check(object) || PyLong_Check(object)) {
return PyObject_Str(object);
} else if (PyList_Check(object)) {
PyObject *result;
if (Py_EnterRecursiveCall(" while encoding a JSON array from a Python list"))
return NULL;
result = encode_list(object);
Py_LeaveRecursiveCall();
return result;
} else if (PyTuple_Check(object)) {
PyObject *result;
if (Py_EnterRecursiveCall(" while encoding a JSON array from a Python tuple"))
return NULL;
result = encode_tuple(object);
Py_LeaveRecursiveCall();
return result;
} else if (PyDict_Check(object)) { // use PyMapping_Check(object) instead? -Dan
PyObject *result;
if (Py_EnterRecursiveCall(" while encoding a JSON object"))
return NULL;
result = encode_dict(object);
Py_LeaveRecursiveCall();
return result;
} else {
PyErr_SetString(JSON_EncodeError, "object is not JSON encodable");
return NULL;
}
}
对于容器类型,如list、dict, 递归的调用encode_object
else if (PyList_Check(object)) {
PyObject *result;
if (Py_EnterRecursiveCall(" while encoding a JSON array from a Python list"))
return NULL;
result = encode_list(object);
Py_LeaveRecursiveCall();
return result;
}
static PyObject*
encode_list(PyObject *list)
{
Py_ssize_t i;
PyObject *s, *temp;
PyObject *pieces = NULL, *result = NULL;
PyListObject *v = (PyListObject*) list;
i = Py_ReprEnter((PyObject*)v);
if (i != 0) {
if (i > 0) {
PyErr_SetString(JSON_EncodeError, "a list with references to "
"itself is not JSON encodable");
}
return NULL;
}
if (v->ob_size == 0) {
result = PyString_FromString("[]");
goto Done;
}
pieces = PyList_New(0);
if (pieces == NULL)
goto Done;
/* Do repr() on each element. Note that this may mutate the list,
* so must refetch the list size on each iteration. */
for (i = 0; i < v->ob_size; ++i) {
int status;
s = encode_object(v->ob_item[i]); // 对list的每一项,递归调用encode_object
if (s == NULL)
goto Done;
status = PyList_Append(pieces, s);
Py_DECREF(s); /* append created a new ref */
if (status < 0)
goto Done;
}
/* Add "[]" decorations to the first and last items. */
assert(PyList_GET_SIZE(pieces) > 0);
s = PyString_FromString("[");
if (s == NULL)
goto Done;
temp = PyList_GET_ITEM(pieces, 0);
PyString_ConcatAndDel(&s, temp);
PyList_SET_ITEM(pieces, 0, s);
if (s == NULL)
goto Done;
s = PyString_FromString("]");
if (s == NULL)
goto Done;
temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
PyString_ConcatAndDel(&temp, s);
PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
if (temp == NULL)
goto Done;
/* Paste them all together with ", " between. */
s = PyString_FromString(", ");
if (s == NULL)
goto Done;
result = _PyString_Join(s, pieces);
Py_DECREF(s);
Done:
Py_XDECREF(pieces);
Py_ReprLeave((PyObject *)v);
return result;
}
decode
static PyObject*
decode_json(JSONData *jsondata)
{
PyObject *object;
skipSpaces(jsondata);
switch(*jsondata->ptr) {
case 0:
PyErr_SetString(JSON_DecodeError, "empty JSON description");
return NULL;
case '{':
if (Py_EnterRecursiveCall(" while decoding a JSON object"))
return NULL;
object = decode_object(jsondata);
Py_LeaveRecursiveCall();
break;
case '[':
if (Py_EnterRecursiveCall(" while decoding a JSON array"))
return NULL;
object = decode_array(jsondata);
Py_LeaveRecursiveCall();
break;
case '"':
object = decode_string(jsondata);
break;
case 't':
case 'f':
object = decode_bool(jsondata);
break;
case 'n':
object = decode_null(jsondata);
break;
case 'N':
object = decode_nan(jsondata);
break;
case 'I':
object = decode_inf(jsondata);
break;
case '+':
case '-':
if (*(jsondata->ptr+1) == 'I') {
object = decode_inf(jsondata);
break;
}
// fall through
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
object = decode_number(jsondata);
break;
default:
PyErr_SetString(JSON_DecodeError, "cannot parse JSON description");
return NULL;
}
return object;
}