1
0
Fork 0
mirror of https://github.com/ultrajson/ultrajson.git synced 2024-05-28 18:16:02 +02:00

Add option to disable forward slash escape

Ref issue #144
This commit is contained in:
Mathieu Leplatre 2015-03-31 23:32:14 +02:00
parent 2015faa5d0
commit d169b7ccbc
6 changed files with 52 additions and 8 deletions

View File

@ -59,7 +59,16 @@ Controls how many decimals to encode for double or decimal values. Default is 9:
'3'
>>> ujson.dumps(math.pi, double_precision=4)
'3.1416'
escape_forward_slashes
----------------------
Controls whether forward slashes (``/``) are escaped. Default is True::
>>> ujson.dumps('http://esn.me')
'"http:\/\/esn.me"'
>>> ujson.dumps('http://esn.me', escape_forward_slashes=False)
'"http://esn.me"'
~~~~~~~~~~~~~~~~
Decoders options
~~~~~~~~~~~~~~~~

View File

@ -241,6 +241,10 @@ typedef struct __JSONObjectEncoder
If true, '<', '>', and '&' characters will be encoded as \u003c, \u003e, and \u0026, respectively. If false, no special encoding will be used. */
int encodeHTMLChars;
/*
If true, '/' will be encoded as \/. If false, no escaping. */
int escapeForwardSlashes;
/*
Private pointer to be used by the caller. Passed as encoder_prv in JSONTypeContext */
void *prv;

View File

@ -184,7 +184,6 @@ int Buffer_EscapeStringUnvalidated (JSONObjectEncoder *enc, const char *io, cons
}
case '\"': (*of++) = '\\'; (*of++) = '\"'; break;
case '\\': (*of++) = '\\'; (*of++) = '\\'; break;
case '/': (*of++) = '\\'; (*of++) = '/'; break;
case '\b': (*of++) = '\\'; (*of++) = 'b'; break;
case '\f': (*of++) = '\\'; (*of++) = 'f'; break;
case '\n': (*of++) = '\\'; (*of++) = 'n'; break;
@ -206,6 +205,19 @@ int Buffer_EscapeStringUnvalidated (JSONObjectEncoder *enc, const char *io, cons
break;
}
}
case '/':
{
if (enc->escapeForwardSlashes)
{
(*of++) = '\\'; (*of++) = '/';
}
else
{
// Same as default case below.
(*of++) = (*io);
}
break;
}
case 0x01:
case 0x02:
case 0x03:
@ -423,9 +435,17 @@ int Buffer_EscapeStringValidated (JSOBJ obj, JSONObjectEncoder *enc, const char
case 22:
case 24:
{
*(of++) = *( (char *) (g_escapeChars + utflen + 0));
*(of++) = *( (char *) (g_escapeChars + utflen + 1));
io ++;
if (enc->escapeForwardSlashes)
{
*(of++) = *( (char *) (g_escapeChars + utflen + 0));
*(of++) = *( (char *) (g_escapeChars + utflen + 1));
io ++;
}
else
{
// Same as case 1 above.
*(of++) = (*io++);
}
continue;
}
// This can never happen, it's here to make L4 VC++ happy

View File

@ -818,7 +818,7 @@ char *Object_iterGetName(JSOBJ obj, JSONTypeContext *tc, size_t *outLen)
PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "obj", "ensure_ascii", "double_precision", "encode_html_chars", NULL};
static char *kwlist[] = { "obj", "ensure_ascii", "double_precision", "encode_html_chars", "escape_forward_slashes", NULL };
char buffer[65536];
char *ret;
@ -826,6 +826,7 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
PyObject *oinput = NULL;
PyObject *oensureAscii = NULL;
PyObject *oencodeHTMLChars = NULL;
PyObject *oescapeForwardSlashes = NULL;
JSONObjectEncoder encoder =
{
@ -848,13 +849,14 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
10, // default double precision setting
1, //forceAscii
0, //encodeHTMLChars
1, //escapeForwardSlashes
NULL, //prv
};
PRINTMARK();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OiO", kwlist, &oinput, &oensureAscii, &encoder.doublePrecision, &oencodeHTMLChars))
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OiOO", kwlist, &oinput, &oensureAscii, &encoder.doublePrecision, &oencodeHTMLChars, &oescapeForwardSlashes))
{
return NULL;
}
@ -869,6 +871,11 @@ PyObject* objToJSON(PyObject* self, PyObject *args, PyObject *kwargs)
encoder.encodeHTMLChars = 1;
}
if (oescapeForwardSlashes != NULL && !PyObject_IsTrue(oescapeForwardSlashes))
{
encoder.escapeForwardSlashes = 0;
}
PRINTMARK();
ret = JSON_EncodeObject (oinput, &encoder, buffer, sizeof (buffer));
PRINTMARK();

View File

@ -53,7 +53,7 @@ PyObject* objToJSONFile(PyObject* self, PyObject *args, PyObject *kwargs);
PyObject* JSONFileToObj(PyObject* self, PyObject *args, PyObject *kwargs);
#define ENCODER_HELP_TEXT "Use ensure_ascii=false to output UTF-8. Pass in double_precision to alter the maximum digit precision of doubles. Set encode_html_chars=True to encode < > & as unicode escape sequences."
#define ENCODER_HELP_TEXT "Use ensure_ascii=false to output UTF-8. Pass in double_precision to alter the maximum digit precision of doubles. Set encode_html_chars=True to encode < > & as unicode escape sequences. Set escape_forward_slashes=False to prevent escaping / characters."
static PyMethodDef ujsonMethods[] = {
{"encode", (PyCFunction) objToJSON, METH_VARARGS | METH_KEYWORDS, "Converts arbitrary object recursivly into JSON. " ENCODER_HELP_TEXT},

View File

@ -49,6 +49,7 @@ class UltraJSONTests(unittest.TestCase):
input = "A string \\ / \b \f \n \r \t </script> &"
not_html_encoded = '"A string \\\\ \\/ \\b \\f \\n \\r \\t <\\/script> &"'
html_encoded = '"A string \\\\ \\/ \\b \\f \\n \\r \\t \\u003c\\/script\\u003e \\u0026"'
not_slashes_escaped = input
def helper(expected_output, **encode_kwargs):
output = ujson.encode(input, **encode_kwargs)
@ -68,6 +69,9 @@ class UltraJSONTests(unittest.TestCase):
helper(html_encoded, ensure_ascii=True, encode_html_chars=True)
helper(html_encoded, ensure_ascii=False, encode_html_chars=True)
# Do escape forward slashes if disabled.
helper(not_slashes_escaped, escape_forward_slashes=False)
def testWriteEscapedString(self):
self.assertEqual('"\\u003cimg src=\'\\u0026amp;\'\\/\\u003e"', ujson.dumps("<img src='&amp;'/>", encode_html_chars=True))