Skip to content

Commit

Permalink
Call Decoder.string(), if that is implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
lelit committed Aug 21, 2017
1 parent 76a76a9 commit 17cd5ab
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
37 changes: 37 additions & 0 deletions docs/decoder.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,40 @@
>>> od = OrderedDecoder()
>>> type(od('{"foo": "bar"}'))
<class 'collections.OrderedDict'>

.. method:: string(s)

:param s: a ``str`` instance
:returns: a new value

This method, when implemented, is called whenever a *JSON string* has
been completely parsed, and can be used to replace it with an arbitrary
different value:

.. doctest::

>>> class SwapStringCase(Decoder):
... def string(self, s):
... return s.swapcase()
...
>>> ssc = SwapStringCase()
>>> ssc('"Hello World!"')
'hELLO wORLD!'

Note that it is called **after** the recognition of dates and UUIDs,
when `datetime_mode` and/or `uuid_mode` are specified:

.. doctest::

>>> class DDMMYYYY(Decoder):
... def string(self, s):
... if len(s) == 8 and s.isdigit():
... dd = int(s[:2])
... mm = int(s[2:4])
... yyyy = int(s[-4:])
... return (yyyy, mm, dd)
... return s
...
>>> ddmmyyyy = DDMMYYYY(datetime_mode=DM_ISO8601)
>>> ddmmyyyy('["2017-08-21", "21082017"]')
[datetime.date(2017, 8, 21), (2017, 8, 21)]
24 changes: 24 additions & 0 deletions rapidjson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static PyObject* start_object_name = NULL;
static PyObject* end_object_name = NULL;
static PyObject* default_name = NULL;
static PyObject* end_array_name = NULL;
static PyObject* string_name = NULL;

static PyObject* minus_inf_string_value = NULL;
static PyObject* nan_string_value = NULL;
Expand Down Expand Up @@ -157,6 +158,7 @@ struct PyHandler {
PyObject* decoderStartObject;
PyObject* decoderEndObject;
PyObject* decoderEndArray;
PyObject* decoderString;
PyObject* root;
PyObject* objectHook;
DatetimeMode datetimeMode;
Expand All @@ -168,6 +170,7 @@ struct PyHandler {
: decoderStartObject(NULL),
decoderEndObject(NULL),
decoderEndArray(NULL),
decoderString(NULL),
root(NULL),
objectHook(hook),
datetimeMode(dm),
Expand All @@ -189,13 +192,18 @@ struct PyHandler {
decoderEndArray = PyObject_GetAttr(decoder, end_array_name);
Py_INCREF(decoderEndArray);
}
if (PyObject_HasAttr(decoder, string_name)) {
decoderString = PyObject_GetAttr(decoder, string_name);
Py_INCREF(decoderString);
}
}
}

~PyHandler() {
Py_CLEAR(decoderStartObject);
Py_CLEAR(decoderEndObject);
Py_CLEAR(decoderEndArray);
Py_CLEAR(decoderString);
}

bool Handle(PyObject* value) {
Expand Down Expand Up @@ -912,6 +920,17 @@ struct PyHandler {
return HandleUuid(str, length);

value = PyUnicode_FromStringAndSize(str, length);
if (value == NULL)
return false;

if (decoderString != NULL) {
PyObject* replacement = PyObject_CallFunctionObjArgs(decoderString, value, NULL);
Py_DECREF(value);
if (replacement == NULL)
return false;
value = replacement;
}

return Handle(value);
}
};
Expand Down Expand Up @@ -2707,6 +2726,10 @@ PyInit_rapidjson()
if (end_array_name == NULL)
goto error;

string_name = PyUnicode_InternFromString("string");
if (string_name == NULL)
goto error;

PyObject* m;

m = PyModule_Create(&module);
Expand Down Expand Up @@ -2772,6 +2795,7 @@ PyInit_rapidjson()
Py_CLEAR(end_object_name);
Py_CLEAR(default_name);
Py_CLEAR(end_array_name);
Py_CLEAR(string_name);

return NULL;
}

0 comments on commit 17cd5ab

Please sign in to comment.