diff options
-rw-r--r-- | simplejson/__init__.py | 2 | ||||
-rw-r--r-- | simplejson/_speedups.c | 22 | ||||
-rw-r--r-- | simplejson/encoder.py | 10 | ||||
-rw-r--r-- | simplejson/tests/test_raw_json.py | 30 |
4 files changed, 63 insertions, 1 deletions
diff --git a/simplejson/__init__.py b/simplejson/__init__.py index 84acfa4..37a6012 100644 --- a/simplejson/__init__.py +++ b/simplejson/__init__.py @@ -110,7 +110,7 @@ from decimal import Decimal from .scanner import JSONDecodeError from .decoder import JSONDecoder -from .encoder import JSONEncoder, JSONEncoderForHTML +from .encoder import JSONEncoder, JSONEncoderForHTML, RawJSON def _import_OrderedDict(): import collections try: diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c index 9976464..2d81063 100644 --- a/simplejson/_speedups.c +++ b/simplejson/_speedups.c @@ -245,6 +245,8 @@ static void encoder_dealloc(PyObject *self); static int encoder_clear(PyObject *self); +static int +is_raw_json(PyObject *obj); static PyObject * encoder_stringify_key(PyEncoderObject *s, PyObject *key); static int @@ -277,6 +279,20 @@ moduleinit(void); #define MIN_EXPANSION 6 +static PyObject* RawJSONType; +static int +is_raw_json(PyObject *obj) +{ + if (RawJSONType == NULL) { + PyObject *encoder_module = PyImport_ImportModule("simplejson.encoder"); + RawJSONType = PyObject_GetAttrString(encoder_module, "RawJSON"); + Py_DECREF(encoder_module); + if (RawJSONType == NULL) + return 0; + } + return PyObject_IsInstance(obj, RawJSONType) ? 1 : 0; +} + static int JSON_Accu_Init(JSON_Accu *acc) { @@ -2868,6 +2884,12 @@ encoder_listencode_obj(PyEncoderObject *s, JSON_Accu *rval, PyObject *obj, Py_ss if (encoded != NULL) rv = _steal_accumulate(rval, encoded); } + else if (is_raw_json(obj)) + { + PyObject *encoded = PyObject_GetAttrString(obj, "encoded_json"); + if (encoded != NULL) + rv = _steal_accumulate(rval, encoded); + } else if (PyInt_Check(obj) || PyLong_Check(obj)) { PyObject *encoded; if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj)) { diff --git a/simplejson/encoder.py b/simplejson/encoder.py index d453d09..9c9b81e 100644 --- a/simplejson/encoder.py +++ b/simplejson/encoder.py @@ -39,6 +39,10 @@ for i in [0x2028, 0x2029]: FLOAT_REPR = repr +class RawJSON(object): + def __init__(self, encoded_json): + self.encoded_json = encoded_json + def encode_basestring(s, _PY3=PY3, _q=u('"')): """Return a JSON representation of a Python string @@ -472,6 +476,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if (isinstance(value, string_types) or (_PY3 and isinstance(value, binary_type))): yield buf + _encoder(value) + elif isinstance(value, RawJSON): + yield buf + value.encoded_json elif value is None: yield buf + 'null' elif value is True: @@ -590,6 +596,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if (isinstance(value, string_types) or (_PY3 and isinstance(value, binary_type))): yield _encoder(value) + elif isinstance(value, RawJSON): + yield value.encoded_json elif value is None: yield 'null' elif value is True: @@ -632,6 +640,8 @@ def _make_iterencode(markers, _default, _encoder, _indent, _floatstr, if (isinstance(o, string_types) or (_PY3 and isinstance(o, binary_type))): yield _encoder(o) + elif isinstance(o, RawJSON): + buf + o.encoded_json elif o is None: yield 'null' elif o is True: diff --git a/simplejson/tests/test_raw_json.py b/simplejson/tests/test_raw_json.py new file mode 100644 index 0000000..6fa6349 --- /dev/null +++ b/simplejson/tests/test_raw_json.py @@ -0,0 +1,30 @@ +import unittest +import simplejson as json + +dct1 = { + 'key1': 'value1' +} + +dct2 = { + 'key2': 'value2', + 'd1': dct1 +} + +dct3 = { + 'key2': 'value2', + 'd1': json.dumps(dct1) +} + +dct4 = { + 'key2': 'value2', + 'd1': json.RawJSON(json.dumps(dct1)) +} + + +class TestRawJson(unittest.TestCase): + + def test_normal_str(self): + self.assertNotEqual(json.dumps(dct2), json.dumps(dct3)) + + def test_raw_json_str(self): + self.assertEqual(json.dumps(dct2), json.dumps(dct4)) |